feat: Async Refresh for Regional Access Boundaries#1880
feat: Async Refresh for Regional Access Boundaries#1880vverman wants to merge 10 commits intogoogleapis:feat-tb-safrom
Conversation
…pe. Updated tests.
…rors are now retryable.
oauth2_http/java/com/google/auth/http/HttpCredentialsAdapter.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/http/HttpCredentialsAdapter.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundaryManager.java
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundary.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundaryManager.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundaryProvider.java
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/http/HttpCredentialsAdapter.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundaryManager.java
Outdated
Show resolved
Hide resolved
| @@ -193,33 +228,41 @@ static TrustBoundary refresh( | |||
| .setInitialIntervalMillis(OAuth2Utils.INITIAL_RETRY_INTERVAL_MILLIS) | |||
| .setRandomizationFactor(OAuth2Utils.RETRY_RANDOMIZATION_FACTOR) | |||
| .setMultiplier(OAuth2Utils.RETRY_MULTIPLIER) | |||
| .setMaxElapsedTimeMillis(maxRetryElapsedTimeMillis) | |||
| .build(); | |||
|
|
|||
| HttpUnsuccessfulResponseHandler unsuccessfulResponseHandler = | |||
| new HttpBackOffUnsuccessfulResponseHandler(backoff); | |||
| new HttpBackOffUnsuccessfulResponseHandler(backoff) | |||
| .setBackOffRequired( | |||
| response -> { | |||
| int statusCode = response.getStatusCode(); | |||
| return statusCode == 500 | |||
| || statusCode == 502 | |||
| || statusCode == 503 | |||
| || statusCode == 504; | |||
| }); | |||
There was a problem hiding this comment.
qq, since the server-side will still make the RAB call if we have failure (e.g. no header is attached), can we have this call not have any retries and max duration of like 1-2s?
The reason I'm thinking this way is that the async RAB call uses ForkJoinPool's commonPool. I think we should try to time bound the IO requests that go to that executor pool since that is a JDK executor pool that is shared with the customer's application.
There was a problem hiding this comment.
Yes, while requests will succeed without the RAB header, they are expected to encounter significant latency, hence we retry only on transient server errors which are expected to be short lived.
We'd like to ensure that there are as few requests as possible that go without the x-allowed-locations header.
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundary.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundaryManager.java
Outdated
Show resolved
Hide resolved
|
Thanks for the clarification @vverman! Would it be possible to split the stable RAB + seeding logic into a separate PR? |
| public static final String X_ALLOWED_LOCATIONS_HEADER_KEY = "x-allowed-locations"; | ||
| private static final long serialVersionUID = -2428522338274020302L; | ||
|
|
||
| static final String ENABLE_EXPERIMENT_ENV_VAR = "GOOGLE_AUTH_TRUST_BOUNDARY_ENABLE_EXPERIMENT"; |
There was a problem hiding this comment.
I think we can remove the env var altogether since this is going to a feature branch and we don't need the feature gate for the release.
| * Checks if the trust boundary feature is enabled based on an environment variable. The feature | ||
| * is enabled if the environment variable is set to "true" or "1" (case-insensitive). Any other | ||
| * value, or if the variable is unset, will result in the feature being disabled. | ||
| * Checks if the regional access boundary feature is enabled. The feature is enabled if the |
There was a problem hiding this comment.
Similar to my other comment, I think we can remove this method along with all env var related code, as they shouldn't be present in the final code being merged to main.
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundary.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundaryManager.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundaryManager.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/RegionalAccessBoundaryManager.java
Outdated
Show resolved
Hide resolved
| // Self-signed JWT do not go through the typical OAuth2Credentials.getRequestMetadata() | ||
| // flow. | ||
| // We explicitly trigger it here to ensure the RAB cache is populated/maintained. | ||
| refreshRegionalAccessBoundaryIfExpired(uri, wrappedToken); |
There was a problem hiding this comment.
IIUC, we're triggering a refresh here, but we're not attaching the RAB value to the metadata header if it already exists. It seems like the self signed jwt would never have this header.
There was a problem hiding this comment.
Thank you for this very important observation. Turns out this wasn't caught because my test only checked whether the RABManager had the RAB property set to the expected value and I wasn't checking for whether the header was attached. Which is why this was missed.
I have corrected the logic and the test. I also checked tests of other supported clients and verified that they check the header!
…now considers expiryTime as opposed to start time. Minor fixes.
Contains changes for the feature Regional Access Boundary (Previously Called Trust Boundaries).
The following are salient changes:
Calls to refresh RAB are now all async and in a separate thread.
Logic for refreshing RAB now exists in its own class for cleaner maintenance.
Self-signed jwts are within scope.
Changes to how we trigger RAB refresh and deal with refresh errors.