-
Notifications
You must be signed in to change notification settings - Fork 269
feat: Async Refresh for Regional Access Boundaries #1880
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
base: feat-tb-sa
Are you sure you want to change the base?
feat: Async Refresh for Regional Access Boundaries #1880
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/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
| private static final Pattern INVALID_TOKEN_ERROR = | ||
| Pattern.compile("\\s*error\\s*=\\s*\"?invalid_token\"?"); | ||
|
|
||
| private static final String STALE_RAB_ERROR_MESSAGE = "stale regional access boundary"; |
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.
Still waiting for the backend team to confirm the wording, we might need to update this based on their response. see b/450921839
| LOGGER_PROVIDER, | ||
| Level.INFO, | ||
| null, | ||
| "RAB lookup failed; entering cooldown for " |
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.
| "RAB lookup failed; entering cooldown for " | |
| "Regional Access Boundary lookup failed; entering cooldown for " |
nit: Spell out for user-facing error messages/ logs
| @@ -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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| public final RegionalAccessBoundary getRegionalAccessBoundary() { | ||
| return regionalAccessBoundaryManager.getCachedRAB(); | ||
| } |
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.
are the methods here intentional to be public (e.g. used by the customer)? Can they be package-private.
I know you mentioned the seeded RAB token is used by the customer
| final class TrustBoundary { | ||
| public final class RegionalAccessBoundary implements Serializable { | ||
|
|
||
| public static final String HEADER_KEY = "x-allowed-locations"; |
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.
nit: Can you give this a more descriptive constant name
e.g. perhaps ALLOWED_LOCATIONS_HEADER_KEY
| } | ||
|
|
||
| private static class CooldownState { | ||
| /** The time (in milliseconds) when the current cooldown period started. */ |
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.
nit:
| /** The time (in milliseconds) when the current cooldown period started. */ | |
| /** The time (milliseconds from epoch) when the current cooldown period started. */ |
| List<String> authHeaders = requestMetadata.get(AuthHttpConstants.AUTHORIZATION); | ||
| if (authHeaders != null && !authHeaders.isEmpty()) { | ||
| // Extract the token value to trigger a background Regional Access Boundary refresh. | ||
| String authHeader = authHeaders.get(0); | ||
| if (authHeader.startsWith(AuthHttpConstants.BEARER + " ")) { | ||
| String tokenValue = authHeader.substring((AuthHttpConstants.BEARER + " ").length()); | ||
| // Use a null expiration as JWTs are short-lived anyway. | ||
| AccessToken wrappedToken = new AccessToken(tokenValue, null); | ||
| refreshRegionalAccessBoundaryIfExpired(uri, wrappedToken); | ||
| } | ||
| } |
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.
Add a small comment to explain this custom logic here.
e.g. something like SSJWT's don't go through the typical Oauth2Credential getRequestMetadata() flow that triggers the async RAB
| metadata = new HashMap<>(metadata); | ||
| metadata.put( | ||
| RegionalAccessBoundary.HEADER_KEY, Collections.singletonList(rab.getEncodedLocations())); |
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.
Can you use the ImmuatableMap.Builder() from guava to build the new metadata
|
Thanks for the clarification @vverman! Would it be possible to split the stable RAB + seeding logic into a separate PR? |
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.