Improve backoff/retry when SDK is configured with bad credentials

Description

Suggested Release Note:

Reduced the rate at which messages appear in the server's `http_access.log` when invalid credentials are provided.

An SDK configured with bad credentials spams the server with HTTP requests for "/pools/default/b/<bucket-name>". It would be nice to throttle these requests somehow.

To reproduce:

public static void main(String... args) throws Exception { Cluster cluster = Cluster.connect("127.0.0.1", "Administrator", "bad-password"); Bucket bucket = cluster.bucket("default"); MINUTES.sleep(10); }

and tail var/lib/couchbase/logs/http_access.log

Edit: This can also occur when an SDK has correct credentials, but that user does not have RBAC to access the bucket. If they have access to no buckets, 401 Unauthorized will be returned, if they have access to another bucket 403 Forbidden will be returned.

Environment

None

Gerrit Reviews

None

Release Notes Description

None

Activity

Show:

Michael Reiche January 31, 2024 at 10:27 PM
Edited

https://github.com/couchbase/couchbase-jvm-clients/blob/370dc4a2a18ff28e3cd3827c89cff11219e3c768/core-io/src/main/java/com/couchbase/client/core/config/DefaultConfigurationProvider.java#L974

Should also use a long delay for Unauthorized (401) and Forbidden (403) - something like this :

boolean bucketNotFound = f instanceof BucketNotFoundDuringLoadException;
boolean bucketNotReady = f instanceof BucketNotReadyDuringLoadException;

// there is an UNAUTHORIZED -> NO_ACCESS mapping in HttpProtocol.decodeStatus(),
// but there is no specific exception thrown for it in ClusterManagerBucketLoader.discoverConfig().
boolean bucketNoAccess = f.getMessage() != null && f.getMessage().contains("status=NO_ACCESS");

// there is no FORBIDDEN (403) mapping in HttpProtocol.decodeStatus(), it comes out as UNKNOWN.
// even if there was a mapping, there is not specific exception thrown for it in
// ClusterManagerBucketLoader.discoverConfig()
// this is dumped as bytes in the message:
// {"message":"Forbidden. User needs the following permissions","permissions":["cluster.bucket["bucketName"].settings!read"]}
boolean bucketForbidden = f.getMessage() != null && f.getMessage().contains("status=UNKNOWN}"); // 403 and everything other than 401

// For bucket not found or not ready wait a bit longer, retry the rest quickly
Duration delay = bucketNotFound || bucketNotReady || bucketNoAccess || bucketForbidden
? Duration.ofMillis(500)
: Duration.ofMillis(1);

It's not obvious how to get a 403 error. See https://couchbasecloud.atlassian.net/browse/MB-60622

Fixed
Pinned fields
Click on the next to a field label to start pinning.

Details

Assignee

Reporter

Story Points

Sprint

Fix versions

Priority

Instabug

Open Instabug

PagerDuty

Sentry

Zendesk Support

Created January 30, 2024 at 10:39 PM
Updated May 20, 2024 at 12:35 AM
Resolved March 20, 2024 at 7:21 PM
Instabug