Add regenerate-bot-tokens operation for JWT key rotation#26477
Add regenerate-bot-tokens operation for JWT key rotation#26477
Conversation
Add a new `regenerate-bot-tokens` subcommand to OpenMetadataOperations that regenerates JWT tokens for all bot users. This is needed when rotating JWT signing keys or changing the cluster name (e.g., during disaster recovery from POV to PROD). The command: - Iterates through all non-deleted bots with pagination - Regenerates JWT tokens only for bots using JWT authentication - Skips bots without associated users or non-JWT auth mechanisms - Displays results in an ASCII table with status per bot Closes open-metadata/openmetadata-collate#3157 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
openmetadata-service/src/main/java/org/openmetadata/service/util/OpenMetadataOperations.java
Outdated
Show resolved
Hide resolved
openmetadata-service/src/main/java/org/openmetadata/service/util/OpenMetadataOperations.java
Outdated
Show resolved
Hide resolved
- Token expiry is now a CLI parameter (--expiry) defaulting to Unlimited, so operators can choose OneHour, One, Seven, Thirty, Sixty, Ninety, or Unlimited when regenerating - Add null guard on getPaging() to prevent NPE on empty result sets Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🟡 Playwright Results — all passed (23 flaky)✅ 3330 passed · ❌ 0 failed · 🟡 23 flaky · ⏭️ 183 skipped
🟡 23 flaky test(s) (passed on retry)
How to debug locally# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip # view trace |
Move the token regeneration logic from the ops CLI into a new REST endpoint PUT /v1/users/regenerateBotTokens (admin-only). The ops command now calls the server API via HTTP, following the same pattern as deploy-pipelines. This keeps business logic in the server and the ops CLI as a thin HTTP client. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After JWT key rotation, all existing bot tokens are invalid — including the ingestion-bot token needed to authenticate against the server API. This command must operate directly on the database to recover from that state. Added a doc comment explaining the reasoning. Also reverts the UserResource endpoint added in the previous commit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tern Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
listAll/listAfter use setFieldsInBulk which only calls registered fieldFetchers (tags, owners, etc.) — not the entity-specific setFields override. BotRepository.setFields populates botUser via a relationship lookup, but this is never called in bulk listing. Fetch each bot individually with getByName which triggers setFields properly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
openmetadata-service/src/main/java/org/openmetadata/service/util/OpenMetadataOperations.java
Show resolved
Hide resolved
Tests cover token regeneration producing new tokens, respecting expiry parameters, and handling multiple bots independently. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Unlimited tokens generated in the same second produce identical JWTs (same iat, null exp). Changed test to use different expiry values so the tokens are guaranteed to differ. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code Review ✅ Approved 5 resolved / 5 findingsAdds regenerate-bot-tokens operation for JWT key rotation, addressing hardcoded expiry overrides, null pointer exceptions on pagination boundaries, URL injection via CLI params, and error handling for failed regenerations. All findings resolved. ✅ 5 resolved✅ Bug: Hardcoded Unlimited expiry overrides bots' existing token expiry
✅ Bug: NPE when
|
| Auto-apply | Compact |
|
|
Was this helpful? React with 👍 / 👎 | Gitar
|
…ta#26477) * Add regenerate-bot-tokens operation for JWT key rotation Add a new `regenerate-bot-tokens` subcommand to OpenMetadataOperations that regenerates JWT tokens for all bot users. This is needed when rotating JWT signing keys or changing the cluster name (e.g., during disaster recovery from POV to PROD). The command: - Iterates through all non-deleted bots with pagination - Regenerates JWT tokens only for bots using JWT authentication - Skips bots without associated users or non-JWT auth mechanisms - Displays results in an ASCII table with status per bot Closes open-metadata/openmetadata-collate#3157 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix review: add --expiry CLI parameter and null-guard paging - Token expiry is now a CLI parameter (--expiry) defaulting to Unlimited, so operators can choose OneHour, One, Seven, Thirty, Sixty, Ninety, or Unlimited when regenerating - Add null guard on getPaging() to prevent NPE on empty result sets Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Document regenerate-bot-tokens expiry values in help output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Move bot token regeneration logic to server API Move the token regeneration logic from the ops CLI into a new REST endpoint PUT /v1/users/regenerateBotTokens (admin-only). The ops command now calls the server API via HTTP, following the same pattern as deploy-pipelines. This keeps business logic in the server and the ops CLI as a thin HTTP client. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Revert server API approach, use direct DB access for token regeneration After JWT key rotation, all existing bot tokens are invalid — including the ingestion-bot token needed to authenticate against the server API. This command must operate directly on the database to recover from that state. Added a doc comment explaining the reasoning. Also reverts the UserResource endpoint added in the previous commit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix compilation: use fully-qualified ResultList to match existing pattern Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix botUser always null: fetch each bot individually via getByName listAll/listAfter use setFieldsInBulk which only calls registered fieldFetchers (tags, owners, etc.) — not the entity-specific setFields override. BotRepository.setFields populates botUser via a relationship lookup, but this is never called in bulk listing. Fetch each bot individually with getByName which triggers setFields properly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add integration tests for regenerate-bot-tokens operation Tests cover token regeneration producing new tokens, respecting expiry parameters, and handling multiple bots independently. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix flaky test: use different expiries to guarantee distinct tokens Unlimited tokens generated in the same second produce identical JWTs (same iat, null exp). Changed test to use different expiry values so the tokens are guaranteed to differ. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * format --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>



Summary
regenerate-bot-tokenssubcommand toOpenMetadataOperationsthat regenerates JWT tokens for all bot usersTest plan
./openmetadata-ops.sh regenerate-bot-tokens -c conf/openmetadata.yamlagainst a local environment with bots configuredCloses open-metadata/openmetadata-collate#3157