1

hope all is well with you. I'm currently working with a cassandra database and I'm almost done with it. Currently I am deploying my services and an error occurred. To work best with cassandra in my nestjs back-end I use the framework https://github.com/ifaim/nestjs-express-cassandra This works in the backend with the framework https://github.com/masumsoft/express-cassandra (which is actively updated and used a lot). But now the problem is that according to the documentation of datastax (where my cassandra db is hosted) I have to deposit a secureConnectBundle to be able to connect to my database.

My config

Console Error

Running Database

Example from Datastax

DataStax

However, I have found very little online about this and generally I find more examples of how to connect to your datastax database without secureConnectBundle than with. So far with me but without success and therefore I ask here. I really hope that I do not have to change the framework because that would probably mean the end of this project.

 export const cassandraOptions: ExpressCassandraModuleOptions = {
  clientOptions: {
    contactPoints: [
      'e68eb980-c5c3-47fa-a423-472652519805-europe-west1.db.astra.datastax.com',
    ],
    protocolOptions: { port: 9042 },
    keyspace: 'partii',
    queryOptions: {
      fetchSize: 100,
      consistency: 1,
    },
    authProvider: new auth.PlainTextAuthProvider('X', 'X'),
  },
  ormOptions: {
    createKeyspace: false,
    defaultReplicationStrategy: {
      class: 'SimpleStrategy',
      replication_factor: 1,
    },
    migration: 'safe',
  },
};
Aaron
  • 55,518
  • 11
  • 116
  • 132
Shift
  • 31
  • 4
  • 1
    Welcome to StackOverflow; this reading about [reproducible examples](https://stackoverflow.com/help/minimal-reproducible-example) may be helpful, as adding images to external sites make it difficult to do so – Carlos Monroy Nieblas Dec 18 '22 at 03:13
  • The error message indicates a timeout to the Cassandra node, have you verified that from host that is running `nest` is able to communicate with that host in the port 9042? something like `telnet 34.77.135.39 9042` – Carlos Monroy Nieblas Dec 18 '22 at 03:18
  • If i try to telnet 34.77.135.39 9042 i get a "Connection timed out" – Shift Dec 18 '22 at 12:33
  • Ok, so it seems that this may be a networking issue then, if the host is unable to connect to the database, in the port `9042`, Ansible won't be able to connect either – Carlos Monroy Nieblas Dec 18 '22 at 16:36
  • I'm using the normal setup from Datastax where you can't change anything in networking or anything like that and they are the company currently behind cassandra so I doubt it's their fault. Does anyone have any idea how I can fix the error? – Shift Dec 18 '22 at 20:09
  • This seems to not be related to the database configuration, but to networking; in this context, I'm using `networking` as the communication between the server where the nest application is running, and the servers where the database are located; `telnet` is a command that is not related to Cassandra or the client. This can be caused by firewalls, or the network configuration, are those physical machines? are you using AWS/GCP? – Carlos Monroy Nieblas Dec 18 '22 at 21:04
  • I use GCloud through Datastax. (I linked a screenshot from my datastax page) I just tested the telnet command from one of my vps servers and could not connect. – Shift Dec 19 '22 at 09:07
  • { "host": "e68eb980-c5c3-47fa-a423-472652519805-europe-west1.db.astra.datastax.com", "port": 29080, "cql_port": 29042, "keyspace": "partii", "localDC": "europe-west1", "caCertLocation": "./ca.crt", "keyLocation": "./key", "certLocation": "./cert", "keyStoreLocation": "./identity.jks", "keyStorePassword": "ISNdc3jL47H6OVnm9", "trustStoreLocation": "./trustStore.jks", "trustStorePassword": "s7vwSX83T29UPgJBk", "csvLocation": "./data", "pfxCertPassword": "X9vRo016GLWUYE5V" } The secure bundle config – Shift Dec 19 '22 at 10:01

4 Answers4

1

You appear to be using DataStax Astra DB. DataStax Astra DB does not connect on the Cassandra default 9042 port, but rather on 29042. However, even with that correct, you'll still have to pass along the SSL info, which is tricky to get correct manually. That's why the recommendation of referencing the secure connect bundle is the easy path.

You're right in that there don't appear to be any examples of using Astra DB with Express Cassandra. The good news, is that Express Cassandra looks like it uses the Cassandra nodejs driver underneath. That means that the client options are likely to be the same/similar. Try something like this:

export const cassandraOptions: ExpressCassandraModuleOptions = {
  clientOptions: {
    cloud: { secureConnectBundle: 'path/to/secure-connect-bundle.zip' },
    credentials: { username: 'clientid', password: 'secret' }
 },
 ormOptions: {
   createKeyspace: false,
   defaultReplicationStrategy: {
     class: 'SimpleStrategy',
     replication_factor: 1,
   },
   migration: 'safe',
 },
};

And if that doesn't work, maybe swap out the credentials line with authProvider you're using above.

Aaron
  • 55,518
  • 11
  • 116
  • 132
  • 1
    If I don't define any contact points, I get the error "Contacts points are not defined. If I define some they are used and not the secureConnectBundle. I also just checked and if I'm not mistaken only one connection is created here (no client). https://github.com/ifaim/nestjs-express-cassandra/blob/75d3cccd99b99cf4c659bcf70060c4bbaa8f08ad/lib/express-casandra-core.module.ts#L131 https://github.com/ifaim/nestjs-express-cassandra/blob/75d3cccd99b99cf4c659bcf70060c4bbaa8f08ad/lib/orm/interfaces/externals/express-cassandra-connection.interface.ts – Shift Dec 19 '22 at 16:01
  • @Shift got it. Let me do some digging and see what I can find for you here. – Aaron Dec 19 '22 at 21:24
1

You can only create a keyspace via the DevOps API or via the GUI. You may want to follow the examples provided here.

Madhavan
  • 758
  • 4
  • 8
  • The example doesn't help me because I can't change the framework and I have disabled the automatic creation of the keyspace in my config. – Shift Dec 19 '22 at 15:53
  • Got it. I see that the [DataStax Astra DB](https://github.com/datastax/nodejs-driver/blob/master/CHANGELOG.md#430) support was only added beginning `4.3.0` version and if this leverages anything lower, it won't understand how to leverage the [Secure Connect Bundle](https://docs.datastax.com/en/astra-serverless/docs/connect/secure-connect-bundle.html). That might be something to check if you're leveraging the minimally supported version. – Madhavan Dec 19 '22 at 23:39
  • I see that there is [an open issue/feature request](https://github.com/ifaim/nestjs-express-cassandra/issues/8) to upgrade to cassandra-driver 4.x series here. I don't think this will be able to connect to Astra DB until that is completed. – Madhavan Dec 19 '22 at 23:40
1

In the meantime I decided to set up the ssl connection manually and it works. Now I just have to fix the error.

apollo.model.tablecreation.dbschemaquery: Error while retrieveing Schema of DB Table "NoHostAvailableError: All host(s) tried for query failed. First host tried, 34.79.132.94:29080: Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altna mes: IP: 34.79.132.94 is not in the cert's list: . See innerErrors.

Implemented files from secure bundle by myself

Shift
  • 31
  • 4
  • Hi @Shift, could you try the same procedure that the [Java legacy drivers](https://docs.datastax.com/en/astra-serverless/docs/connect/drivers/legacy-drivers.html) leverage to see if that route works for you? From the above, it is not clear that whether you followed the procedure described here or you followed something else? Could you give this a go and see if you're unblocked? – Madhavan Dec 21 '22 at 23:04
1

Its solved.

import {
  auth,
  ExpressCassandraModuleOptions,
} from '@iaminfinity/express-cassandra';
// get fs to read the certificate
import * as fs from 'fs';
// get path to resolve the certificate path
import * as path from 'path';

export const cassandraOptions: () => ExpressCassandraModuleOptions = () => {
  const sslOptions = {
    rejectUnauthorized: true,
    cert: fs.readFileSync(path.resolve(__dirname, '../src/database/cert')),
    key: fs.readFileSync(path.resolve(__dirname, '../src/database/key.pem')),
    ca: fs.readFileSync(path.resolve(__dirname, '../src/database/ca.crt')),
  };

  return {
    clientOptions: {
      contactPoints: [
        'host',
      ],
      protocolOptions: { port: 29042 },
      keyspace: 'partii',
      queryOptions: {
        fetchSize: 100,
        consistency: 1,
      },
      sslOptions: {
        ...sslOptions,
        host: '34.79.236.16',
        checkServerIdentity: function (host, cert) {
          return undefined;
        },
      },
      authProvider: new auth.PlainTextAuthProvider(
        'id',
        'secret',
      ),
    },
    ormOptions: {
      createKeyspace: false,
      defaultReplicationStrategy: {
        class: 'SimpleStrategy',
        replication_factor: 1,
      },
      migration: 'alter',
    },
  };
};
Shift
  • 31
  • 4
  • Excellent! Glad you got this figured out. I was going to build up an example like this next. – Aaron Dec 21 '22 at 13:54