question

FelipeMalaquias-4566 avatar image
0 Votes"
FelipeMalaquias-4566 asked FelipeMalaquias-4566 edited

Cannot connect to mongodb while allowInsecureConnection is false

Hi,

I know this is somehow a basic question but I'm new to Azure world and NodeJS, and I could not find any example so far on how to solve this connection issue on my local tests.

Scenario:
Testing Azure Serverless Function at localhost establishing connection to Azure Cosmos DB, and later on, deploy it and run it on the same virtual network.

I imagine that I have to use OpenSSL to create a certificate (and probably self-signed is not enough?) and deploy the private key somewhere in Cosmos DB settings, and somehow import the public key in my Node env, but I have no idea on how to do this.
Unfortunately, the NodeJS function example does not work out of the box because of this error either, and I see no concrete solution for it anywhere in the docs (actually, the links in the 'quick start' section of cosmos db in portal are broken - 404). May someone please give me some hints?

Thanks!

azure-functionsazure-cosmos-db
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello @FelipeMalaquias-4566 , Welcome to Microsoft QnA. Thank you for your question. Your function app is running on which plan?

0 Votes 0 ·

Hi! It's running on a free account.

0 Votes 0 ·
JayaC-MSFT avatar image
0 Votes"
JayaC-MSFT answered FelipeMalaquias-4566 commented

Hello @FelipeMalaquias-4566 , If its running on consumption plan , you may think of :

  1. Whitelist all the IP addresses of an Azure Region/Zone.

  2. Using the VPC peering, connect the Azure function and App Service to VNET first. {This is an expensive approach.}

In that case I would recommend you to consider using service tags : https://docs.microsoft.com/en-us/azure/virtual-network/service-tags-overview#available-service-tags

Also if you need static, dedicated IP addresses, we recommend App Service Environments (the Isolated tier of App Service plans). { Again this could be an expensive approach as mentioned in point no.2 }
https://docs.microsoft.com/en-us/azure/azure-functions/ip-addresses#dedicated-ip-addresses

For ref : https://www.mongodb.com/blog/post/how-to-integrate-azure-functions-with-mongodb

https://thecodebarbarian.com/getting-started-with-azure-functions-and-mongodb.html


· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello @JayaC-MSFT,

Thanks for your answer but I don't think this actually solves the problem with my current scenario. I'm not using MongoDB Atlas, I'm using CosmosDB with MongoAPI. So the networking is not an issue in this case, but the TLS connection.

1) I see for example that CosmosClient API seems to not support certificate in the DB constructor, differently from standard MongoClient driver.

2) Which certificate is expected by CosmoDB instance? Do I need to set it up with my own key/CA?

Thanks,

Felipe

0 Votes 0 ·
FelipeMalaquias-4566 avatar image
2 Votes"
FelipeMalaquias-4566 answered FelipeMalaquias-4566 edited

Hi @JayaC-MSFT,

I believe the network is not the issue in this case, but the TLS connection. The function is able to reach the DB but the connection is refused because apparently I need a certificate to connect to the mongoDB. I'm not using MongoDB Atlas, but Azure Cosmos DB with MongoAPI, so the links also didn't help in this case.

I decided to delete all the CosmosDB resources and use Azure SQL instead. In this case, it is working just fine. I had to adapt a bit the examples I found though, because the function is by default async and it needs some tweaks for working properly.

This is how it currently looks like:

 // @ts-check
    
 import { AzureFunction, Context, HttpRequest } from "@azure/functions"
 import { Connection, Request, TYPES } from "tedious";
    
 const httpTrigger: AzureFunction = function (context: Context, req: HttpRequest) {
     context.log('HTTP trigger function processed a request.');
    
     if (req.body && req.body.email) {
         // Create connection to database
         const config = {
             authentication: {
                 options: {
                     userName: process.env.DB_USERNAME,
                     password: process.env.DB_PASSWORD
                 },
                 type: "default"
                 },
                 server: process.env.DB_SERVER,
                 options: {
                     database: process.env.DB_NAME,
                     encrypt: true
                 }
         };
    
         const connection = new Connection(config);
         // Attempt to connect and execute queries if connection goes through
         connection.on("connect", err => {
             if (err) {
                 context.log(err.message);
                 context.res = { status: 500 };
                 context.done();
             } else {
                 // Read all rows from table
                 const request = new Request(
                     `BEGIN
                         IF NOT EXISTS (SELECT * FROM Subscriptions s
                                         WHERE s.email = @email)
                         BEGIN
                             INSERT INTO Subscriptions (name, email)
                             VALUES (@name, @email)
                         END
                     END`,
                     (err, rowCount) => {
                         if (err) {
                             context.log(err.message);
                             context.res = { status: 500 };
                         } else {
                             context.log(`${rowCount} row(s) created`);
                             context.res = { status: 200 };
                         }
                         connection.close();
                         context.done();
                     }
                 );
                 request.addParameter('name',  TYPES.NVarChar, req.body.name);
                 request.addParameter('email',  TYPES.NVarChar, req.body.email);
    
                 request.on("row", columns => {
                     columns.forEach(column => {
                     console.log("%s\t%s", column.metadata.colName, column.value);
                     });
                 });
    
                 connection.execSql(request);
             }
         });
         connection.connect();
     }
     else {
         context.res = { status: 400 };
         context.done();
     }
 };
    
 export default httpTrigger;
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.