camunda-community-hub / zeebe-client-node-js

Node.js client library for Zeebe Microservices Orchestration Engine
https://camunda-community-hub.github.io/zeebe-client-node-js/
Apache License 2.0
152 stars 38 forks source link

Custom root certs not being passed to Camunda Cloud connection #319

Closed nikku closed 1 year ago

nikku commented 1 year ago

I have a corporate, SSL terminating cloud firewall that sits between zeebe-node and Camunda 8 SaaS. That firewall serves a custom SSL certificate for C8 SaaS endpoint and I must mark that one as trusted.

As it looks like, this library assumes that C8 SaaS won't use custom SSL certificates for oAuth; at least I was not able to configure it using the customSSL.rootCerts and/or oAuth.customRootCert option:

const client = new ZBClient('SOME_C8_SAAS_ADDRESS', {
  camundaCloud: {
    clientId: 'CLIENT_ID',
    clientSecret:
      'CLIENT_SECRET',
    clusterId: 'CLUSTER_ID',
    clusterRegion: 'CLUSTER_REGION'
  },
  useTLS: true,
  customSSL: {
    rootCerts
  }
});

As a result I receive the following logs in a downstream application (Camunda Desktop Modeler):

ERROR app:zeebe-api Failed to connect with config (secrets omitted): {
  endpoint: {
    type: 'camundaCloud',
    clientId: 'CLIENT_ID'
  }
} RequestError: self signed certificate in certificate chain
    at ClientRequest.<anonymous> (camunda-modeler-5.11.0-win-x64\resources\app.asar\node_modules\got\dist\source\core\index.js:970:111)
    at Object.onceWrapper (node:events:628:26)
    at ClientRequest.emit (node:events:525:35)
    at ClientRequest.emit (node:domain:489:12)
    ...
  code: 'SELF_SIGNED_CERT_IN_CHAIN',
  ...

Note the use of got which indicates that oAuth token retrival failed (rather than the actual connection).

Expected Behavior

I can connect to C8 SaaS, using custom certificates.

Current Behavior

Connection to C8 SaaS does not pick up certificates that I provide through customSSL.rootCerts.

Possible Solution

In general I think it makes sense that the client respects customSSL.rootCerts for oAuth, too. This would give us the ability to configure custom certificates once and use them for both oAuth, and the actual grpc connection:

const client = new ZBClient('SOME_C8_SAAS_ADDRESS', {
  camundaCloud: {
    clientId: 'CLIENT_ID',
    clientSecret:
      'CLIENT_SECRET',
    clusterId: 'CLUSTER_ID',
    clusterRegion: 'CLUSTER_REGION'
  },
  useTLS: true,
  customSSL: {
    rootCerts
  }
});

Alternatively we could allow to configure oAuth with only customRootCert and respect that property:

const client = new ZBClient('SOME_C8_SAAS_ADDRESS', {
  camundaCloud: {
    clientId: 'CLIENT_ID',
    clientSecret:
      'CLIENT_SECRET',
    clusterId: 'CLUSTER_ID',
    clusterRegion: 'CLUSTER_REGION'
  },
  useTLS: true,
  customSSL: {
    rootCerts
  },
  oAuth: {
    customRootCert: rootCerts
  }
});

The later though currently fails due to type constraints:

Type '{ customRootCert: Buffer; }' is missing the following properties from type 'OAuthProviderConfig': url, audience, clientId, clientSecret

Steps to Reproduce

Due to the nature of this issue reproduction is fairly complicated. What you can do is to replicate the configuration issue in a test case

Context (Environment)

Camunda 8 SaaS, connecting to it through corporate network with SSL terminating firewall / custom SSL certificate.

Detailed Description

Possible Implementation