oracle / oracle-r2dbc

R2DBC Driver for Oracle Database
https://oracle.com
Other
193 stars 40 forks source link

option(OracleR2dbcOptions.TLS_SERVER_DN_MATCH, "false") does not work #102

Closed sourabhdug closed 1 year ago

sourabhdug commented 1 year ago
ConnectionFactoryOptions.builder()
                .option(ConnectionFactoryOptions.DRIVER, "oracle")
                .option(ConnectionFactoryOptions.HOST, HOST)
                .option(ConnectionFactoryOptions.PORT, 1569)
                .option(ConnectionFactoryOptions.DATABASE, SERVICE_NAME)
                .option(ConnectionFactoryOptions.USER, "...")
                .option(ConnectionFactoryOptions.PASSWORD, "....")
                .option(OracleR2dbcOptions.TLS_SERVER_DN_MATCH, "false")

                // To configure a TCPS/SSL/TLS enabled ConnectionFactory, set the SSL
                // option to true, and then specify the path to a wallet location...
                .option(ConnectionFactoryOptions.SSL, true)

     return Mono.from(
                ConnectionFactories.get(url)
                        .create());

Above results in an error of the following trace

{
 "timestamp": "2022-11-03T01:02:06,211Z",
 "level": "ERROR",
 "thread": "ForkJoinPool.commonPool-worker-5",
 "message": "Operator called default onErrorDropped",
 "logger": "reactor.core.publisher.Operators",
 "throwable": {
  "class": "reactor.core.Exceptions$ErrorCallbackNotImplemented",
  "msg": "io.r2dbc.spi.R2dbcTransientResourceException: [17002] [08006] IO Error: Mismatch with the server cert DN. (CONNECTION_ID=....)",
  "cause": {
   "class": "io.r2dbc.spi.R2dbcTransientResourceException",
   "msg": "IO Error: Mismatch with the server cert DN. (CONNECTION_ID=......)",
   "stack": [
    "oracle.r2dbc.impl.OracleR2dbcExceptions.toR2dbcException(OracleR2dbcExceptions.java:214)",
    "reactor.core.publisher.Flux.lambda$onErrorMap$29(Flux.java:6943)",
    "reactor.core.publisher.Flux.lambda$onErrorResume$30(Flux.java:6996)",
    "reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94)",
    "org.reactivestreams.FlowAdapters$FlowToReactiveSubscriber.onError(FlowAdapters.java:216)",
    "oracle.jdbc.datasource.impl.OracleDataSource$ConnectionPublisher$ConnectionSubscription.emitError(OracleDataSource.java:2912)",
    "oracle.jdbc.datasource.impl.OracleDataSource$ConnectionPublisher$ConnectionSubscription.lambda$publishConnectionAsync$0(OracleDataSource.java:2885)",
    "java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)",
    "java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)",
    "java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)",
    "java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:610)",
    "java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:840)",
    "java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:479)",
    "java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)",
    "java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)",
    "java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)",
    "java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)",
    "java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)"]
  }
 }
}

however adding

                .option(OracleR2dbcOptions.TLS_SERVER_CERT_DN, "....")

with expected DN causes the query and connection to succeed!

Dependencies

  implementation 'io.r2dbc:r2dbc-spi:1.0.0.RELEASE'
    implementation "com.oracle.database.jdbc:ojdbc11:21.7.0.0"
    implementation "com.oracle.database.r2dbc:oracle-r2dbc:1.0.0"

Oracle Version

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Michael-A-McMahon commented 1 year ago

Thank you for showing me this. It definitely looks like a bug :( I'll have time to debug tomorrow. I'll update once I learn more...

Michael-A-McMahon commented 1 year ago

I've found the root cause: Oracle JDBC enables DN matching by default when using a URL of the form: jdbc:oracle:thin:@tcps:... Oracle R2DBC uses this form of URL when ConnectionFactoryOptions.SSL is set to true.

In Oracle R2DBC 1.0.0, we can work around this by configuring a descriptor with PROTOCOL=TCPS:

    ConnectionFactoryOptions options =
      ConnectionFactoryOptions.builder()
        .option(ConnectionFactoryOptions.DRIVER, "oracle")
        .option(OracleR2dbcOptions.DESCRIPTOR,
          "(DESCRIPTION=" +
            "(ADDRESS=(PROTOCOL=TCPS)(HOST=your.db.host.com)(PORT=1522))" +
            "(CONNECT_DATA=(SERVICE_NAME=your.db.service.name)))")
        .option(ConnectionFactoryOptions.USER, "...")
        .option(ConnectionFactoryOptions.PASSWORD, "...")
        .build();

For the next release, I will fix this so that we don't need the work around.

sourabhdug commented 1 year ago

Thank you @Michael-A-McMahon I will try the work around, that would be definitely better than having to specify the entire DN!