How do I use Azure AD Authentication with node-mssql? - node.js

So I got a connection working using tedious but the options available in node-mssql for handling JSON are something really useful that I would like to have access to.
The documentation for node-mssql says you can pass an object with authentication settings that tedious would use and it will override the user/password properties but it's definitely not doing that. I can confirm because the error message comes back with the value for the user property.
Is there something wrong with the config object?
const sqlConfig = {
server: process.env.SQL_SERVER,
database: process.env.DATABASE_NAME,
user: "root.user",
password: "password",
options:
{
encrypt: true,
authentication: {
type: "azure-active-directory-password",
options: {
userName: "root.options.authentication.options.userName",
password: "password"
}
},
}
};

Here's the example using node-mssql and azure-active-directory-password(supports Azure AD from tedious#4.1.0):
const config = {
server: 'yoursqlserver.database.windows.net',
database: 'yourdb',
authentication: {
type: "azure-active-directory-password",
options: {
userName: "bob#contoso.com",
password: "password",
}
}
}
Ref here:
https://stackoverflow.com/a/58386825/10549281
https://stackoverflow.com/a/56145320/10549281.
https://github.com/tediousjs/tedious/issues/416#issuecomment-441364272

So there are packages for mssql and node-mssql. I installed node-mssql but was working with the documentation for mssql. I am an idiot.
Thanks to everyone who looked at this and especially Leon.

Related

Sequelize authenticate using Managed Identity to Azure postgres

Facing a connection error when trying to connect to Azure postgres instance using azure Managed identity. My app is developed on Typescript and I am using Sequelize as the ORM (sequelize npm v6.6.2). I am using the following config to establish connection to the database but this fails to authenticate.
config: Options = {
dialect: 'postgres',
logging: false,
dialectOptions : {
authentication: {
type: 'azure-active-directory-msi-vm',
options: {
clientId: <AZURE_CLIENT_ID>,
},
},
}
}
.
.
.
sequelize = new Sequelize(<DB_URL>, config)
I was able to successfully connect if I use password, by just replacing the dialectOptions with 'password'.
I have verified that I am able to connect to a Azure SQL Server instance using the below configuration without an issue.
config: Options = {
database: <AZURE_SQL_DB>,
host: <AZURE_SQL_SERVER>,
dialect: 'mssql',
logging: false,
dialectOptions: {
authentication: {
type: 'azure-active-directory-msi-vm',
options: {
clientId: <AZURE_CLIENT_ID>,
},
},
},
}
.
.
sequelize = new Sequelize(config)
NOTE: For this to work for MSSQL, I had to set the user-assigned managed identity as the 'Azure Active Directory Admin' in the server settings. So I have set it for the postgres instance as well.
Can someone tell me what I am doing wrong here, or is this capability not available yet on Azure Postgres instances?

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.

How to set up postgresql config with heroku and nodejs?

This is my first time try to host nodeJS application - built with hapi.js, typeorm and postgresql - on heroku. I've create two apps on heroku - for "staging" (server-staging) and "production" (server-prod) - that using same code but will use different configuration. Why different configuration? because each application on heroku will use different postgres credential, as it's attached as an add-ons.
objective
My objective/main question is How and where I have to set the database config for my application?
I use .env file (which I ignore in .gitignore - I don't want to put the credential in my repo) to connect the application to my local database. Here is how the .env looks like:
HOST=localhost
PORT=3001
TYPEORM_CONNECTION=postgres
TYPEORM_HOST=localhost
TYPEORM_USERNAME=postgres
TYPEORM_PASSWORD=password
TYPEORM_DATABASE=database
TYPEORM_PORT=5432
TYPEORM_SYNCHRONIZE=true
TYPEORM_LOGGING=false
In the application, I never do/write code such process.env.TYPEORM_USERNAME since its done by the typeorm node_modules. What I do to start the connection is by doing this:
const server = new Hapi.Server({
port: process.env.PORT,
host: process.env.HOST,
routes: {
cors: Cors,
},
});
await server.register(Plugins);
server.route(Router);
await createConnection();
await server.start();
And my application automatically connected to the specified database as defined in the .env. Now, in heroku, the credential is lies here:
All information lies there, but, [Q1] I don't know how to tell my application (of course, without store the credential in my code/repo) that I have to use the config as defined in above picture? Also, as stated in above image, "Heroku rotates credentials periodically and updates applications where this database is attached.". Does it means the credentials will changed periodically? [Q2] If yes, is there any way to make my application auto recognise the new credential?
Sorry if my explanation make confused. If you did not understand what I am trying to achieve, please ask things that you don't understand, so I can fix/update my question to make it understandable.
Anyway, I found this example first-example and second-example. But, they are using process.env.DATABASE_URL, which contain credential. I think, it means that they not ignore their .env file in their repo?
*) Note: Q1 means Question 1, and so for the rest
Write a ormconfig.js file in the root of your repo. This way you can access the environment variables like the url provided from heroku and you don't have credentials in your repo.
require('dotenv').config();
module.exports = [
{
name: 'default',
type: 'postgres',
url: process.env.DATABASE_URL,
synchronize: false,
logging: false,
entities: ['dist/entities/*.*'],
migrations: ['dist/database/migrations/**/*.js'],
subscribers: ['dist/database/subscribers/**/*.js'],
cli: {
entitiesDir: 'dist/entities',
migrationsDir: 'dist/database/migrations',
subscribersDir: 'dist/database/subscribers',
},
},
{
name: 'development',
type: 'postgres',
host: process.env.POSTGRES_HOST,
port: process.env.POSTGRES_PORT,
username: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DB,
synchronize: true,
logging: true,
entities: ['src/entities/*.*'],
migrations: ['src/database/migrations/**/*.ts'],
subscribers: ['src/database/subscribers/**/*.ts'],
cli: {
entitiesDir: 'src/entities',
migrationsDir: 'src/database/migrations',
subscribersDir: 'src/database/subscribers',
},
},
];
With this configuration you can then get a specific configuration in javascript/typescript:
let connectionOptions: ConnectionOptions;
if(process.env.NODE_ENV ==='development') {
connectionOptions = await getConnectionOptions("development");
} else {
connectionOptions = await getConnectionOptions("default");
}
await createConnection(connectionOptions);

Syntax for defining 'pool' in KNEX/BookshelfJS

Firstly, I'm new to everything here... and new to StackOverflow, so apologies in advance for being a newbie and I'm ready for my thrashing... LOL.
We use a Heroku.addon for Postgres and utilize/reference environment variables globally to access the right database.
We have a config.js file in our application's root directory like:
db: process.env.DB_URL || {
client: 'pg',
connection: {
database: 'db_name',
user: 'user_name'
}
},
Would someone here be able to guide me on how to integrate code that initializes 'custom pool' information into this setup like the example found on
[http://knexjs.org/#Installation-pooling][http://knexjs.org/#Installation-pooling]
var knex = require('knex')({
client: 'mysql',
connection: {
host : '127.0.0.1',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test'
},
pool: { min: 0, max: 7 }
});
On Heroku, process.env.DB_URL is a complex URL that is similar to:
postgres://(redacted)#ec5-87-1-47-54.compute-1.amazonaws.com:5432/d8n2e9ebd0q9it
So, I am hoping there is a clean way to also pass 'custom pool' information as well either here or in another file/location.
The database is referenced throughout the backend of our application via Bookshelf/Knex. The reference to bookshelf looks similar to:
var knex = require('knex')(config.db);
var bookshelf = require('bookshelf')(knex);
You might be able to do it by reading just connection details from env variable, like this:
db: {
client: 'pg',
connection: process.env.DB_URL || {
database: 'db_name',
user: 'user_name'
},
pool: { min:5, max:20 }
},

Accessing a Shared Server with Backslashes in the Address via Node Express

I've been struggling to get Express to work with a shared server looking like this:
53.165.137.28\NAME,94273
I get the following error:
Error: Failed to connect to 53.165.137.28:undefined in 15000ms
I tried escaping using double backslashes "\\", but it doesn't work. Also, using %5C also didn't work.
Note:
I can query this server via SQL Server Management Studio just fine.
What am I missing?
I managed to solve it.
Instead of this:
var dbCofing = {
user: 'USER',
password: 'PASS',
server: '53.165.137.28\\NAME,94273',
database: 'DATABASE'
}
I used the following:
var dbCofing = {
user: 'USER',
password: 'PASS',
server: '53.165.137.28',
instanceName: 'NAME',
port: 94273,
database: 'DATABASE'
}

Resources