-
Notifications
You must be signed in to change notification settings - Fork 24
fix: only request a token when near expiration #2370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @strantalis, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
Summary of Changes
Hello team,
Gemini here to provide a summary of this pull request. The primary goal of this PR, as indicated by the title, is to optimize the Keycloak integration within the Entity Resolution Service (ERS). Previously, the service would perform a client login to Keycloak to obtain an access token on potentially every request that required interaction with Keycloak. This PR changes that behavior to only request a new token when the currently cached token is nil, expired, or nearing its expiration.
This is achieved by adding state to the ERS service struct to hold the Keycloak connector and its expiration time, protected by a mutex for concurrent access. A new internal method getConnector is introduced to manage the token lifecycle, fetching a new token only when necessary. The existing handler functions (ResolveEntities, CreateEntityChainFromJwt, CreateEntityChainsFromTokens) and helper functions now utilize this cached connector instance.
Highlights
- Keycloak Token Caching: The Keycloak connector and its access token are now cached within the ERS service instance. A mutex is used to ensure thread-safe access to the connector.
- Token Refresh Logic: A new
getConnectormethod handles retrieving the connector. It checks if the current token is valid and not nearing expiration (with a 60-second buffer). If the token is missing or expiring, it performs a client login to fetch a new one. - Refactored Keycloak Interaction: The functions that interact with Keycloak (
EntityResolution,CreateEntityChainFromJwt,CreateEntityChainsFromTokens,getEntitiesFromToken,getServiceAccountClient) have been updated to accept the cached connector instance as a parameter, removing the need for them to repeatedly call the oldgetKCClientfunction. - Removed Redundant Login Logic: The
getKCClientfunction, which previously performed a Keycloak client login on every call, has been removed as its functionality is now integrated into thegetConnectormethod. - Test Updates: Unit tests have been updated to reflect the changes in function signatures, passing a mock or initialized connector where required. The test package name was also changed from
keycloak_testtokeycloakto allow access to internal types for testing.
Changelog
Click here to see the changelog
- service/entityresolution/keycloak/entity_resolution.go
- Added
syncandtimeimports (lines 11-12). - Added
connectorandconnectorMufields toKeycloakEntityResolutionServicestruct (lines 49-50). - Changed receiver for
ResolveEntitiesandCreateEntityChainFromJwtmethods to pointer (*KeycloakEntityResolutionService) (lines 73, 86). - Added
connectorfield toKeyCloakConnectorstruct (line 124). - Added
connectorparameter toCreateEntityChainFromJwtfunction (line 131). - Added
connectorparameter toEntityResolutionfunction (line 148). - Removed the
getKCClientfunction (lines 337-364). - Added
connectorparameter togetEntitiesFromTokenfunction (line 373). - Added
connectorparameter togetServiceAccountClientfunction (line 441). - Added
getConnectormethod toKeycloakEntityResolutionServicefor managing the cached Keycloak connection and token refresh (lines 478-513).
- Added
- service/entityresolution/keycloak/entity_resolution_test.go
- Changed package name from
keycloak_testtokeycloak(line 1). - Removed explicit import alias for
keycloakpackage (line 15). - Updated return types of
testKeycloakConfigandtestKeycloakConfigInferIDto use local types (KeycloakConfig,InferredIdentityConfig,EntityImpliedFrom) (lines 78, 89, 96). - Initialized
KeyCloakConnectorinstances in various test functions (Test_KCEntityResolutionByClientId,Test_KCEntityResolutionByEmail,Test_KCEntityResolutionByUsername,Test_KCEntityResolutionByGroupEmail,Test_KCEntityResolutionNotFoundError,Test_JwtClientAndUsernameClientCredentials,Test_JwtClientAndUsernamePasswordPub,Test_JwtClientAndUsernamePasswordPriv,Test_JwtClientAndUsernameAuthPub,Test_JwtClientAndUsernameAuthPriv,Test_JwtClientAndUsernameImplicitPub,Test_JwtClientAndUsernameImplicitPriv,Test_JwtClientAndClientTokenExchange,Test_JwtMultiple,Test_KCEntityResolutionNotFoundInferEmail,Test_KCEntityResolutionNotFoundInferClientId,Test_KCEntityResolutionNotFoundNotInferUsername) (e.g., lines 159-162). - Passed the initialized
connectorto calls toEntityResolutionandCreateEntityChainFromJwt(e.g., lines 164, 341). - Updated error message comparison in
Test_KCEntityResolutionNotFoundErrorandTest_KCEntityResolutionNotFoundNotInferUsernameto use localErrGetRetrievalFailed(lines 321, 322, 652, 653).
- Changed package name from
- service/entityresolution/keycloak/v2/entity_resolution.go
- Added
syncandtimeimports (lines 11-12). - Added
connectorandconnectorMufields toEntityResolutionServiceV2struct (lines 48-49). - Changed receiver for
ResolveEntitiesandCreateEntityChainsFromTokensmethods to pointer (*EntityResolutionServiceV2) (lines 72, 83). - Added
expiresAtfield toConnectorstruct (line 120). - Added
connectorparameter toCreateEntityChainsFromTokensfunction (line 127). - Added
connectorparameter toEntityResolutionfunction (line 144). - Removed the
getKCClientfunction (lines 337-364). - Added
connectorparameter togetEntitiesFromTokenfunction (line 369). - Added
connectorparameter togetServiceAccountClientfunction (line 437). - Added
getConnectormethod toEntityResolutionServiceV2for managing the cached Keycloak connection and token refresh (lines 474-509).
- Added
- service/entityresolution/keycloak/v2/entity_resolution_test.go
- Changed package name from
keycloak_testtokeycloak(line 1). - Removed explicit import alias for
keycloakpackage (line 15). - Updated return types of
testConfigandtestConfigInferIDto use local types (Config,InferredIdentityConfig,EntityImpliedFrom) (lines 78, 89, 96). - Initialized
Connectorinstances in various test functions (Test_KCEntityResolutionByClientId,Test_KCEntityResolutionByEmail,Test_KCEntityResolutionByUsername,Test_KCEntityResolutionByGroupEmail,Test_KCEntityResolutionNotFoundError,Test_JwtClientAndUsernameClientCredentials,Test_JwtClientAndUsernamePasswordPub,Test_JwtClientAndUsernamePasswordPriv,Test_JwtClientAndUsernameAuthPub,Test_JwtClientAndUsernameAuthPriv,Test_JwtClientAndUsernameImplicitPub,Test_JwtClientAndUsernameImplicitPriv,Test_JwtClientAndClientTokenExchange,Test_JwtMultiple,Test_KCEntityResolutionNotFoundInferEmail,Test_KCEntityResolutionNotFoundInferClientId,Test_KCEntityResolutionNotFoundNotInferUsername) (e.g., lines 160-163). - Passed the initialized
connectorto calls toEntityResolutionandCreateEntityChainsFromTokens(e.g., lines 164, 340). - Updated error message comparison in
Test_KCEntityResolutionNotFoundErrorandTest_KCEntityResolutionNotFoundNotInferUsernameto use localErrGetRetrievalFailed(lines 321, 322, 643, 644).
- Changed package name from
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
A token in the cache,
Saves a network dash.
Check time, then renew,
Efficiency is true.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces an important optimization for the Keycloak Entity Resolution Service by caching the authentication token and only refreshing it when it's nil, expired, or nearing expiration. This should significantly reduce the number of login requests to Keycloak, improving performance and reducing load.
The core logic in the new getConnector method appears sound, incorporating a mutex for thread-safe access and a refresh buffer for proactive token renewal. The changes are consistently applied across both the v1 and v2 ERS implementations, and method receivers have been correctly updated to pointers to manage the shared connector state.
While the existing tests have been adapted to the new function signatures, the PR description is quite minimal. Providing more details on the changes and testing strategy would be helpful for reviewers.
Overall, this is a valuable improvement. My main suggestion revolves around enhancing test coverage for the new token management logic, as detailed in the specific comment.
Summary of Findings
- Token Caching and Refresh Logic: The PR successfully implements token caching and refresh logic in the
getConnectormethod, only requesting new tokens when necessary. This includes mutex protection for concurrent access and a refresh buffer. - Method Receiver Updates: Service methods (
ResolveEntities,CreateEntityChainFromJwt, etc.) were correctly changed to use pointer receivers (*KeycloakEntityResolutionService) to allow modification of the internalconnectorstate. - Test Adaptations: Existing unit tests were updated to pass the new
KeyCloakConnector/Connectorinstance to helper functions, accommodating the refactoring. - Test Coverage for
getConnector: The newgetConnectormethod, which contains the core token management logic (caching, expiry checks, refresh), is not unit-tested in isolation. Adding dedicated tests for this method would improve robustness and maintainability. (Commented with 'medium' severity) - Test Package Renaming (Not Commented - Low Severity): Test packages were renamed (e.g.,
keycloak_testtokeycloak), shifting from a black-box to a white-box testing style. This is an acceptable change, likely to simplify testing of internal components.
Merge Readiness
The pull request introduces a significant and valuable optimization for token handling. The core implementation is well done. However, to ensure the robustness of the new token management logic in getConnector, I recommend adding dedicated unit tests for this critical component as suggested in the review comments. Addressing this medium severity testing concern would increase confidence in the change. Therefore, I suggest these changes be considered before merging. As an AI reviewer, I am not authorized to approve pull requests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not worth blocking this, but you could rely on the s.idpConfig.TokenBuffer state within s.getConnector instead of passing it as an argument to each call.
|
/backport |
|
Successfully created backport PR for |
### Proposed Changes * ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions (cherry picked from commit 556d95e)
### Proposed Changes * ### Checklist - [ ] I have added or updated unit tests - [ ] I have added or updated integration tests (if appropriate) - [ ] I have added or updated documentation ### Testing Instructions (cherry picked from commit 556d95e)
🤖 I have created a release *beep* *boop* --- ## [0.7.0](service/v0.6.0...service/v0.7.0) (2025-06-24) ### ⚠ BREAKING CHANGES * **policy:** disable kas grants in favor of key mappings ([#2220](#2220)) ### Features * **authz:** Add caching to keycloak ERS ([#2466](#2466)) ([f5b0a06](f5b0a06)) * **authz:** auth svc registered resource GetDecision support ([#2392](#2392)) ([5405674](5405674)) * **authz:** authz v2 GetBulkDecision ([#2448](#2448)) ([0da3363](0da3363)) * **authz:** cache entitlement policy within authorization service ([#2457](#2457)) ([c16361c](c16361c)) * **authz:** ensure logging parity between authz v2 and v1 ([#2443](#2443)) ([ef68586](ef68586)) * **core:** add cache manager ([#2449](#2449)) ([2b062c5](2b062c5)) * **core:** consume RPC interceptor request context metadata in logging ([#2442](#2442)) ([2769c48](2769c48)) * **core:** DSPX-609 - add cli-client to keycloak provisioning ([#2396](#2396)) ([48e7489](48e7489)) * **core:** ERS cache setup, fix cache initialization ([#2458](#2458)) ([d0c6938](d0c6938)) * inject logger and cache manager to key managers ([#2461](#2461)) ([9292162](9292162)) * **kas:** expose provider config from key details. ([#2459](#2459)) ([0e7d39a](0e7d39a)) * **main:** Add Close() method to cache manager ([#2465](#2465)) ([32630d6](32630d6)) * **policy:** disable kas grants in favor of key mappings ([#2220](#2220)) ([30f8cf5](30f8cf5)) * **policy:** Restrict deletion of pc with used key. ([#2414](#2414)) ([3b40a46](3b40a46)) * **sdk:** allow Connect-Protocol-Version RPC header for cors ([#2437](#2437)) ([4bf241e](4bf241e)) ### Bug Fixes * **core:** remove generics on new platform cache manager and client ([#2456](#2456)) ([98c3c16](98c3c16)) * **core:** replace opentdf-public client with cli-client ([#2422](#2422)) ([fb18525](fb18525)) * **deps:** bump github.com/casbin/casbin/v2 from 2.106.0 to 2.107.0 in /service in the external group ([#2416](#2416)) ([43afd48](43afd48)) * **deps:** bump github.com/opentdf/platform/protocol/go from 0.4.0 to 0.5.0 in /service ([#2470](#2470)) ([3a73fc9](3a73fc9)) * **deps:** bump github.com/opentdf/platform/sdk from 0.4.7 to 0.5.0 in /service ([#2473](#2473)) ([ad37476](ad37476)) * **deps:** bump the external group across 1 directory with 2 updates ([#2450](#2450)) ([9d8d1f1](9d8d1f1)) * **deps:** bump the external group across 1 directory with 2 updates ([#2472](#2472)) ([d45b3c8](d45b3c8)) * only request a token when near expiration ([#2370](#2370)) ([556d95e](556d95e)) * **policy:** fix casing bug and get provider config on update. ([#2403](#2403)) ([a52b8f9](a52b8f9)) * **policy:** properly formatted pem in test fixtures ([#2409](#2409)) ([54ffd23](54ffd23)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com>
Proposed Changes
Checklist
Testing Instructions