Allow wrapper-controlled init to fix jwk_uri backward compatibility (Issue #3054)#3198
Allow wrapper-controlled init to fix jwk_uri backward compatibility (Issue #3054)#3198sh1myama wants to merge 1 commit intoAthenZ:masterfrom
Conversation
Signed-off-by: Shuya Shimaoka <sshimaok@lycorp.co.jp>
Summary of ChangesHello @sh1myama, 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! This pull request addresses a critical backward compatibility issue where the Highlights
Changelog
Activity
Using Gemini Code AssistThe 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 by creating a comment using either
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 Limitations & Feedback Gemini Code Assist 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. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. 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. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request refactors the initialization logic in AuthZpeClient by moving the access token resolver setup to an explicit init() method, which resolves issues with jwk_uri system properties and introduces support for a JWK proxy URI. However, a high-severity Server-Side Request Forgery (SSRF) vulnerability has been identified due to a lack of URL validation for the new JWK proxy URI feature; implementing a strict allow-list for proxy servers is recommended. Furthermore, the new init() method has a potential thread-safety issue and should be made idempotent to prevent race conditions during concurrent initialization.
| if (serverUrl == null || serverUrl.isEmpty()) { | ||
| throw new IllegalArgumentException("Missing required property: " + ZpeConsts.ZPE_PROP_JWK_URI); | ||
| } | ||
| String proxyUrl = System.getProperty(ZpeConsts.ZPE_PROP_JWK_PROXY_URI); |
There was a problem hiding this comment.
The application reads the JWK proxy URL from the system property athenz.zpe.jwk_proxy_uri and uses it to configure an HTTP proxy for fetching the JWK set without validation. An attacker who can set this system property can specify an arbitrary URL, leading to Server-Side Request Forgery (SSRF). This could allow an attacker to redirect network requests to internal services, bypassing firewall controls, or to an attacker-controlled server to intercept sensitive data.
| public static void init() { | ||
| if (LOG.isDebugEnabled()) { | ||
| LOG.debug("Init: load the ZPE"); | ||
| } | ||
| // initialize the access token signing key resolver | ||
|
|
||
| initializeAccessTokenSignKeyResolver(); |
There was a problem hiding this comment.
The new init() method is not thread-safe or idempotent. If called concurrently (e.g., during application startup or in parallel tests), it can lead to race conditions during the initialization of static resources. It's a best practice to ensure that initialization methods like this execute only once.
You can make this method thread-safe and idempotent by using a static flag with double-checked locking. This will ensure the initialization logic is performed safely and exactly one time.
Example:
// Add this field to the class
private static volatile boolean zpeInitialized = false;
// Modify the init() method
public static void init() {
// Quick check without lock
if (zpeInitialized) {
return;
}
synchronized (AuthZpeClient.class) {
// Check again inside the synchronized block
if (zpeInitialized) {
return;
}
if (LOG.isDebugEnabled()) {
LOG.debug("Init: load the ZPE");
}
// ... current init logic ...
initializeAccessTokenSignKeyResolver();
// ... other set calls that were moved ...
zpeInitialized = true;
}
}|
@sh1myama the AuthZpeClient.init() was never required for ZPE functionality. So by moving the actual keyresolver initialization into that function will break most zpe users, so not the correct solution. I'll check in the next couple of days in more detail and will propose how to address your use case. |
|
@havetisyan -san
Thank you for checking. In the following Java decentralized access control sample, the documentation says to initialize the ZPE Client in init when performing authorization checks, so I understood that calling init is mandatory. Even if we apply this change and modify it so that initializeAccessTokenSignKeyResolver is called from init, my understanding is that the behavior will not change as long as the implementation is written to always call init itself. Thank you in advance. |
|
@sh1myama here is what changes we need to make:
this would allow your applications to set the either set the jwks_uri to complete the sign key resolver or jwks_uri_required to false in your application and ignore calling the method completely. |
Description
Context
Changes
Outcome
Contribution Checklist:
Attach Screenshots (Optional)