How to connect to a implicit FTPS server with nodeJS? - node.js

For a project I have to connect to a FTPS server over a implicit connection.
I tried with node-ftp, because it seems that this is the only library, that supports the implicit connection.
I connect using the following code:
var ftpC = new FTPClient();
ftpC.on('ready', function () {
console.log('Connection successful!');
});
ftpC.on('error', function (err) {
console.log(err);
});
console.log('Try to connect to FTP Server...');
ftpC.connect({
host: HOST_TO_CONNECT,
port: 990,
secure: 'implicit',
user: '***',
password: '***',
secureOptions: {
rejectUnauthorized: false
// secureProtocol: 'SSLv23_method',
// ciphers: 'ECDHE-RSA-AES128-GCM-SHA256'
}
})
This code gives me everytime a timeout error. If I raise the timeout, the error comes later.
I tried in secureOptions to add the params rejectUnauthorized, secureProtocol and ciphers, as you can see. None of them is working. Everytime I get this timeout error.
In FileZilla I have no problem to connect. Everything is working fine.
Do someone have a solution for this behavior?
Or is there another plugin for nodejs to connect to a implicit FTPS server?

This appears to be a bug in node-ftp. I've created a PR for it and will update this as soon as it's been fixed.

Related

SSL Routines error when connecting to local DB

So I have this piece of code that is responsible for checking if a connection is valid:
const sequelize = new Sequelize(req.body.database, req.body.user, req.body.password, {
host: req.body.host,
dialect: 'mssql',
port: req.body.port,
dialectOptions: {
options: {
encrypt: true,
}
}
});
sequelize.authenticate().then((err) => {
res.send('Connected');
})
.catch((err) => {
console.log(err.message)
res.send(err.message);
});
This worked perfectly when I was connecting to a local DB on my network. However, when I was trying to connect to a DB through a VPN (simulating a local network) I got the following error:
Failed to connect to 10.1.90.20:1433 - 4C300000:error:0A000102:SSL
routines:ssl_choose_client_version:unsupported
protocol:c:\ws\deps\openssl\openssl\ssl\statem\statem_lib.c:1983:
I read somewhere that adding
cryptoCredentialsDetails: {
minVersion: 'TLSv1'
}
in the options will resolve this but it just gave me a new error:
Failed to connect to 10.1.90.20:1433 - 70290000:error:0A0C0103:SSL
routines:tls_process_key_exchange:internal
error:c:\ws\deps\openssl\openssl\ssl\statem\statem_clnt.c:2255:
Any idea how to fix this?
Keep in mind that both Databases are local however one of them is on a remote network accessible through SSL VPN.

Error connecting NodeJS and SQL Server - Could not connect (sequence)

I'm trying to create a connection with SQL Server and NodeJS as shown below (SQL Server installed locally -> localhost):
It's throwing the following error: ERROR: Failed to connect to MY_SERVER:1433 - Could not connect (sequence)
This didn't work either.
I thought it was a problem with the SQL Server installation, but via Python It works well on the same database.
I'm using SQL Server 2019 and latest NodeJS version.
REFERENCE:
https://learn.microsoft.com/en-us/sql/connect/node-js/step-3-proof-of-concept-connecting-to-sql-using-node-js?view=sql-server-ver15
How to fix this error?
var config = {
server: 'MY_SERVER',
authentication: {
type: 'default',
options: {
userName: 'sa',
password: 'admin'
}
},
options: {
encrypt: false, // I've already tried with "true" also.
database: 'MyDataBase'
}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
console.log("Error: ", err.message);
} else {
console.log("Connected");
}
});
connection.connect();
I got it!! Basically, for NodeJS get connection to SQLServer, the TCP/IP Protocol must be enabled for the MSSQLSERVER Instance, in the SQL Server network settings.
Ref.:
Nodejs connection with mssql showing error
https://store.oceansystems.com/knowledgebase/quickdme-faqs/sql-server-sql-express/configure-sql-express-server-host-enable-tcp-ip-firewall-settings/

How to add an SSL certificate (ca-cert) to node.js environment variables in order to connect to Digital Ocean Postgres Managed Database?

I am currently using node-postgres to create my pool. This is my current code:
const { Pool } = require('pg')
const pgPool = new Pool({
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
host: process.env.PGHOST,
database: process.env.PGDATABASE,
port: process.env.PGPORT,
ssl: {
rejectUnauthorized: true,
// Would like to add line below
// ca: process.env.CACERT,
},
})
I found another post where they read in the cert using 'fs' which can be seen below.
const config = {
database: 'database-name',
host: 'host-or-ip',
user: 'username',
password: 'password',
port: 1234,
// this object will be passed to the TLSSocket constructor
ssl: {
ca: fs.readFileSync('/path/to/digitalOcean/certificate.crt').toString()
}
}
I am unable to do that as I am using git to deploy my application. Specifically Digital Oceans new App Platform. I have attempted reaching out to them with no success. I would prefer not to commit my certificate in my source control. I see a lot of posts of people suggesting to set
ssl : { rejectUnauthorized: false}
That is not the approach I want to take. My code does work with that but I want it to be secure.
Any help is appreciated thanks.
Alright I finally was able to figure it out. I think the issue was multiline and just unfamiliarity with dotenv for my local developing environment.
I was able to get it all working with my code like this. It also worked with the fs.readFileSync() but I didn't want to commit that to my source control.
const { Pool } = require('pg')
const fs = require('fs')
const pgPool = new Pool({
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
host: process.env.PGHOST,
database: process.env.PGDATABASE,
port: process.env.PGPORT,
ssl: {
rejectUnauthorized: true,
// ca: fs.readFileSync(
// `${process.cwd()}/cert/ca-certificate.crt`.toString()
// ),
ca: process.env.CA_CERT,
},
})
.on('connect', () => {
console.log('connected to the database!')
})
.on('error', (err) => {
console.log('error connecting to database ', err)
})
Now in my config.env I had to make it look like this:
CA_CERT="-----BEGIN CERTIFICATE-----\nVALUES HERE WITH NO SPACES AND A \n
AFTER EACH LINE\n-----END CERTIFICATE-----"
I had to keep it as a single line string to have it work. But I was finally to connect with
{rejectUnauthorized:true}
For the digital ocean app platform environment variable, I copied everything including the double quotes and pasted it in there. Seems to work great. I do not think you will be able to have this setting set to true with their $7 development database though. I had to upgrade to the managed one in order to find any CA cert to download.

AWS Lambda - Error: unable to get local issuer certificate

I am trying to connect to an amazon postgreSQL RDS using a NodeJS lambda.
The lambda is in the same VPC as the RDS instance and as far as I can tell the security groups are set up to give the lambda access to the RDS. The lambda is called through API gateway and I'm using knex js as a query builder. When the lambda attempts to connect to the database it throws an "unable to get local issuer certificate" error, but the connection parameters are what I expect them to be.
I know this connection is possible as I've already implemented it in a different environment, without receiving the certificate issue. I've compared the two environments but cannot find any immediate differences.
The connection code looks like this:
import AWS from 'aws-sdk';
import { types } from 'pg';
import { Moment } from 'moment';
import knex from 'knex';
const TIMESTAMP_OID = 1114;
// Example value string: "2018-10-04 12:30:21.199"
types.setTypeParser(TIMESTAMP_OID, (value) => value && new Date(`${value}+00`));
export default class Database {
/**
* Gets the connection information through AWS Secrets Manager
*/
static getConnection = async () => {
const client = new AWS.SecretsManager({
region: '<region>',
});
if (process.env.databaseSecret == null) {
throw 'Database secret not defined';
}
const response = await client
.getSecretValue({ SecretId: process.env.databaseSecret })
.promise();
if (response.SecretString == undefined) {
throw 'Cannot find secret string';
}
return JSON.parse(response.SecretString);
};
static knexConnection = knex({
client: 'postgres',
connection: async () => {
const secret = await Database.getConnection();
return {
host: secret.host,
port: secret.port,
user: secret.username,
password: secret.password,
database: secret.dbname,
ssl: true,
};
},
});
}
Any guidance on how to solve this issue or even where to start looking would be greatly appreciated.
First of all, it is not a good idea to bypass ssl verification, and doing so can make you vulnerable to various exploits and skips a critical step in the TLS handshake.
What you can do is programmatically download the ca certificate chain bundle from Amazon and place it in the root directory of the lambda along side the handler.
wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem -P path/to/handler
Note: you can do this in your buildspec.yaml or in your script that packages the zip file that gets uploaded to aws
Then set the ssl configuration option to the contents of the pem file in your code postgres client configuration, like this:
let pgClient = new postgres.Client({
user: 'postgres',
host: 'rds-cluster.cluster-abc.us-west-2.rds.amazonaws.com',
database: 'mydatabase',
password: 'postgres',
port: 5432,
ssl: {
ca: fs.readFileSync(path.resolve('rds-combined-ca-bundle.pem'), "utf-8")
}
})
I know this is old, but just ran into this today. Running with node 10 and an older version of the pg library worked just fine. Updating to node 16 with pg version 8.x caused this error (simplified):
UNABLE_TO_GET_ISSUER_CERT_LOCALLY
In the past, you could indeed just set the ssl parameter to true or 'true' and it would work with the default AWS RDS certificate. Now, it seems we need to at least tell node/pg to ignore the cert verification (since it's self generated).
Using ssl: 'no-verify' works, enabling ssl and telling pg to ignore the verification of the cert chain.
source
UPDATE
For clarity, here's what the connection string would look like. With Knex, the same client info is passed to pg, so it should look similar to a pg client connection.
static knexConnection = knex({
client: 'postgres',
connection: async () => {
const secret = await Database.getConnection();
return {
host: secret.host,
port: secret.port,
user: secret.username,
password: secret.password,
database: secret.dbname,
ssl: 'no-verify',
};
}

NodeJS Connecting to SQL Server Port Not Found error

I'm trying to connect to SQL Server:
var sql = require("mssql");
var dbConfig = {
server: "LAP12\\INSTANCE1",
database: "SampleDb",
port: 1433,
options: {
trustedConnection: true
}
};
// connect to your database
sql.connect(dbConfig, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select * from SampleTable', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});
});
But I receive this error:
ConnectionError: Port for INSTANCE1 not found in ServerName...
I've tried to follow instructions here https://github.com/patriksimek/node-mssql/issues/130 , but that didn't help. TCP is enabled.
Changing config to this didn't help either:
var dbConfig = {
server: "LAP12",
port: 1433,
options: {
instanceName: 'INSTANCE1',
database: 'SampleDb',
trustedConnection: true,
}
};
Ok, I had the same issue, will try to help.
this is my config exemple
const config = {
user: 'sa',
password: '****',
server: 'DESKTOP-Q5TO47P',
database: 'dbname',
options: {
encrypt: false
}
};
You need to turn on the SQL Server Browser. Go to start up menu or the search and look for SQL Server Configuration Manager. Run it! (Im using 2018 version)
In the left Tab click on SQL Server Services
now in the right tab double click on SQL Server Browser
will open a window, you will see 3 tabs, go for the Service tab
change start mode to Automatic and apply
left click on SQL Server Browser and click restart
Back to the right tab click on SQL Server Network Configuration
then Client Protocols
change TCP/IP to enable
Let me know if it works.
after adding this encrypt: false, application not showing any error neither responding, Its not connecting to DB
In my case the "SQL Browser" is not reachable because the firewall port is not open.
Solution for me is to open the port or change dbConfig to (no instance name, no port):
var dbConfig = {
server: "LAP12",
database: "SampleDb",
options: {
trustedConnection: true
}
};
The port is still closed to SQL-Browser, with that change I can connect to my DB.
My nodejs Package 'mssql'

Resources