1616package com .couchbase ;
1717
1818import com .couchbase .client .core .cnc .RequestSpan ;
19+ import com .couchbase .client .core .env .Authenticator ;
20+ import com .couchbase .client .core .env .CertificateAuthenticator ;
21+ import com .couchbase .client .core .env .PasswordAuthenticator ;
22+ import com .couchbase .client .core .env .SecurityConfig ;
1923import com .couchbase .client .core .io .CollectionIdentifier ;
2024import com .couchbase .client .core .logging .LogRedaction ;
2125import com .couchbase .client .core .logging .RedactionLevel ;
5761import com .couchbase .utils .ResultsUtil ;
5862import com .couchbase .utils .HooksUtil ;
5963// [end]
64+ import com .couchbase .client .performer .core .util .PemUtil ;
6065import com .couchbase .client .performer .core .util .VersionUtil ;
6166import com .couchbase .client .protocol .observability .SpanCreateRequest ;
6267import com .couchbase .client .protocol .observability .SpanCreateResponse ;
8186import com .couchbase .utils .Capabilities ;
8287import com .couchbase .utils .ClusterConnection ;
8388import com .couchbase .utils .OptionsUtil ;
84- import com .couchbase .utils .UserSchedulerUtil ;
8589import io .grpc .Server ;
8690import io .grpc .ServerBuilder ;
8791import io .grpc .Status ;
9498import java .io .IOException ;
9599import java .util .ArrayList ;
96100import java .util .Arrays ;
101+ import java .util .List ;
97102import java .util .Optional ;
98103import java .util .concurrent .ConcurrentHashMap ;
99104import java .util .concurrent .atomic .AtomicReference ;
@@ -206,6 +211,33 @@ protected void customisePerformerCaps(PerformerCapsFetchResponse.Builder respons
206211 response .setPerformerUserAgent ("java-sdk" );
207212 }
208213
214+ private Authenticator getSdkAuthenticator (ClusterConnectionCreateRequest request ) {
215+ if (!request .hasAuthenticator ()) {
216+ return PasswordAuthenticator .create (
217+ request .getClusterUsername (),
218+ request .getClusterPassword ()
219+ );
220+ }
221+
222+ var fitAuth = request .getAuthenticator ();
223+ if (fitAuth .hasPasswordAuth ()) {
224+ var fitUsernameAndPassword = fitAuth .getPasswordAuth ();
225+ return PasswordAuthenticator .create (
226+ fitUsernameAndPassword .getUsername (),
227+ fitUsernameAndPassword .getPassword ()
228+ );
229+ }
230+
231+ if (fitAuth .hasCertificateAuth ()) {
232+ var fitClientCert = fitAuth .getCertificateAuth ();
233+ var privateKey = PemUtil .parseRsaPrivateCrtKey (fitClientCert .getKey ());
234+ var certChain = SecurityConfig .decodeCertificates (List .of (fitClientCert .getCert ()));
235+ return CertificateAuthenticator .fromKey (privateKey , null , certChain );
236+ }
237+
238+ throw new UnsupportedOperationException ("Unrecognized authenticator: " + fitAuth );
239+ }
240+
209241 @ Override
210242 public void clusterConnectionCreate (ClusterConnectionCreateRequest request ,
211243 StreamObserver <ClusterConnectionCreateResponse > responseObserver ) {
@@ -231,15 +263,16 @@ public void clusterConnectionCreate(ClusterConnectionCreateRequest request,
231263 });
232264 });
233265
266+ Authenticator authenticator = getSdkAuthenticator (request );
267+
234268 // [if:3.2.6]
235269 // 3.2.6 added an easy way for SDK users to configure the SDK without having to take ownership of
236270 // ClusterEnvironment management. It also allows passing parameters in the connection string, which
237271 // is not allowed with those externally owned ClusterEnvironments.
238272 var clusterEnvironment = OptionsUtil .convertClusterConfigToConsumer (request , getCluster , onClusterConnectionClose );
239273
240274 var connection = new ClusterConnection (request .getClusterHostname (),
241- request .getClusterUsername (),
242- request .getClusterPassword (),
275+ authenticator ,
243276 clusterEnvironment ,
244277 onClusterConnectionClose );
245278 // [end]
@@ -249,8 +282,7 @@ public void clusterConnectionCreate(ClusterConnectionCreateRequest request,
249282 //? var clusterEnvironment = OptionsUtil.convertClusterConfig(request, getCluster, onClusterConnectionClose);
250283
251284 //? var connection = new ClusterConnection(request.getClusterHostname(),
252- //? request.getClusterUsername(),
253- //? request.getClusterPassword(),
285+ //? authenticator,
254286 //? clusterEnvironment,
255287 //? onClusterConnectionClose);
256288 // [end]
@@ -261,7 +293,7 @@ public void clusterConnectionCreate(ClusterConnectionCreateRequest request,
261293
262294 // Fine to have a default and a per-test connection open, any more suggests a leak
263295 logger .info ("Dumping {} cluster connections for resource leak troubleshooting:" , clusterConnections .size ());
264- clusterConnections .forEach ((key , value ) -> logger .info ("Cluster connection {} {}" , key , value .username ));
296+ clusterConnections .forEach ((key , value ) -> logger .info ("Cluster connection {} {}" , key , value .authenticator ));
265297
266298 responseObserver .onNext (ClusterConnectionCreateResponse .newBuilder ()
267299 .setClusterConnectionCount (clusterConnections .size ())
@@ -291,8 +323,8 @@ public void transactionCreate(TransactionCreateRequest request,
291323 try {
292324 ClusterConnection connection = getClusterConnection (request .getClusterConnectionId ());
293325
294- logger .info ("Starting transaction on cluster connection {} created for user {}" ,
295- request .getClusterConnectionId (), connection .username );
326+ logger .info ("Starting transaction on cluster connection {} created with authenticator {}" ,
327+ request .getClusterConnectionId (), connection .authenticator );
296328
297329 TransactionResult response ;
298330 var counters = new Counters ();
@@ -478,9 +510,9 @@ public void transactionSingleQuery(TransactionSingleQueryRequest request,
478510 try {
479511 var connection = getClusterConnection (request .getClusterConnectionId ());
480512
481- logger .info ("Performing single query transaction on cluster connection {} (user {})" ,
513+ logger .info ("Performing single query transaction on cluster connection {} (authenticator {})" ,
482514 request .getClusterConnectionId (),
483- connection .username );
515+ connection .authenticator );
484516
485517 TransactionSingleQueryResponse ret = SingleQueryTransactionExecutor .execute (request , connection , spans );
486518
0 commit comments