CloudFunction access to MySQL hosted on Computer Engine Virtual Machine - mysql

My CloudFunction needs to access a MariaDB server hosted on a virtual machine from Computer Engine.
Accessing MariaDB by the public IP is working. But I want to access it from the private IP with VPC serverless connector. I don't want my database open on internet.
My VPC is configured with 10.10.0.0/28 adress range.
Screenshot1
My VM have 2 network interfaces :
nic0 on default network : 10.132.0.12 and an external IP (34.XX.XX.XX)
nic1 on vpc-subnet : 10.10.0.7
Screenshot2
CloudFunction is configured with the VPC connector.
Screenshot3
My CloudFunction code :
const mysql = require('mysql');
const ping = require('ping');
const config = require('./config.json');
exports.test = async function(event, context){
//Decode data if is from pubsub call
if(typeof event.data == "string"){
var buff = new Buffer(event.data, 'base64');
var data = JSON.parse(buff.toString('ascii'));
}else{
var data = event.data;
}
const db = mysql.createConnection({
host: data.host,
user: config.db.username,
password: config.db.password,
database: config.db.database
});
ping.sys.probe(data.host, function(isAlive){
var msg = isAlive ? 'host ' + data.host + ' is alive' : 'host ' + data.host + ' is dead';
console.log(msg);
});
db.connect(function(err) {
if (err) throw err;
console.log("Connected to MySQL");
db.query("Select * from Sites limit 1", function (err, result) {
if (err) throw err;
console.log(result);
});
});
}
I tested 10.10.0.7 but I doesn't work.

Related

Connection to mysql works fine locally but not as AWS lambda function

I've created a simple mySQL database that I'm trying to access data from via an AWS Lambda function.
This is a version of the code that runs fine locally:
var mysql = require('mysql');
var config = require('./config.json');
var pool = mysql.createPool({
host : config.dbhost,
user : config.dbuser,
password : config.dbpassword,
database : config.dbname
});
pool.getConnection(function(err, connection) {
// Use the connection
connection.query("SELECT username FROM ClimbingDB.users WHERE email = 'testemail1'", function (error, results, fields) {
// And done with the connection.
connection.release();
// Handle error after the release.
if (error) throw error;
console.log(results);
process.exit();
});
});
This is that code converted to work with AWS Lambda:
var mysql = require('mysql');
var config = require('./config.json');
var pool = mysql.createPool({
host : config.dbhost,
user : config.dbuser,
password : config.dbpassword,
database : config.dbname
});
exports.handler = (event, context, callback) => {
//prevent timeout from waiting event loop
context.callbackWaitsForEmptyEventLoop = false;
pool.getConnection(function(err, connection) {
if (err) return callback(err)
// Use the connection
connection.query("SELECT username FROM ClimbingDB.users WHERE email = 'testemail1'", function (error, results, fields) {
// And done with the connection.
connection.release();
// Handle error after the release.
if (error) return callback(error);
else return callback(null,results);
});
});
};
Which times out with this error message:
{
"errorMessage": "2019-07-19T17:49:04.110Z 2f3e208c-62a6-4e90-b8ec-29398780a2a6 Task timed out after 3.00 seconds"
}
I'm not sure why it doesnt seem to be able to connect. I tried adding the function to a vpc and a security group that has access to RDB's, neither of which do anything. I'm not sure what I'm doing wrong here.
You will need:
The Amazon RDS instance in the same VPC as the AWS Lambda function
A security group on the Lambda function (Lambda-SG)
A security group on the RDS instance (DB-SG) that permits inbound connections on port 3306 from Lambda-SG
That is, DB-SG should specifically reference Lambda-SG (it will turn into a security group ID in the format sg-1234).
You might also want to increase the timeout of the Lambda function to give it a bit more time to run.

Connect from IBM Cloud Functions to MySQL on local host

I want to connect to my MySQL database on a local host which is not in IBM Cloud using IBM Cloud Functions. I am unable to do that.
I have written Node.js code in IBM Cloud Function.
var mysql = require('mysql');
//,cn="server=localhost;port=3306;database=chatbot;uid=root;password=oracle1#;";
var connection = mysql.createConnection({
server: 'localhost',
user: 'root',
port:3306,
password: 'my_password'
});
function main(params) {
try {
//var connection=mysql.createConnection(cn);
connection.connect();
//var s = JSON.stringify(params['user_input']);
//var v = s.substring(1,11);
//var check= conn.querySync("select count(distinct PHONE_NUMBER) where PHONE_NUMBER='"+v+"'");
var rows = connection.query(
"select * from chatbot.customer_data");
//console.log(rows);
connection.end();
return{message:"TRUE:"+rows[0]['PHONE']};
}
catch (e) {
return { message:"error" };
//return{message:"FALSE"};
}
}
Expected result:
TRUE:RESULTSET
Actual Result:
error
This is a pure network issue. The Cloud function running in IBM Cloud does not have a network route that directs to your local host. If you did want that connectivity then you would need to expose the address of your local host using something like a secure gateway service.
var sql = require('mysql');
var connection = sql.createConnection({
host: 'host name',
user: 'user name',
password: 'passwprd',
database: 'database_name'
});
function main(params) {
try {
connection.connect();
var sql="select * from table _name";
connection.query(sql,function(err,result){
return{message:result};
})
//console.log(rows);
connection.end();
}
catch (e) {
return { message:"error" };
//return{message:"FALSE"};
}
}

Error connecting to MySQL from Node-JS server

I am learning to develop server on node-js and have developed a basic get function which retrieves data from MySQL DB hosted on a ubuntu server at digitalocean.
Here's my code:
const express = require('express')
const app = express()
const mysql = require('mysql')
const Client = require('ssh2').Client;
const ssh = new Client();
const db = new Promise(function(resolve, reject){
ssh.on('ready', function() {
ssh.forwardOut(
// source address, this can usually be any valid address
'localhost',
// source port, this can be any valid port number
3333,
// destination address (localhost here refers to the SSH server)
'xxx.xxx.xxx.xxx',
// destination port
22,
function (err, stream) {
if (err) throw err; // SSH error: can also send error in promise ex.
reject(err)
// use `sql` connection as usual
connection = mysql.createConnection({
host : '127.0.0.1',
user : 'user',
password : 'pass',
database: 'mysql',
stream: stream
});
// send connection back in variable depending on success or not
connection.connect(function(err){
if (!err) {
resolve(connection)
} else {
reject(err)
}
});
});
}).connect({
host: 'xxx.xxx.xxx.xxx', //IP address where DB is hosted
port: 22, //Port refering to the IP
username: 'user', //username to loginto the host
password: 'pass' //password to log into host
});
});
//Retrieve route
app.get('/users', (req, res) => {
//console.log("Fetching user with id: " + req.params.id)
const queryString = "SELECT * FROM user"
connection.query(queryString, (err, rows, fields) => {
if(err){
console.log("Failed to query " + err)
res.sendStatus(500)
return
}
console.log("Fetch Succesful")
res.json(rows)
})
})
app.listen(3000, () => {
console.log("Server is up and listerning on port 3000")
})
When I run this code on my local machine it is able to connect to external DB and fetch the data. I have created another server at digitalocean and hosted the same code. However upon running it I get error at connection stating: UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:3306
I tried various solutions available on the platform but could not suceed.
I have written the code accoring to the documentation but still clueless what's causing the error.
Thank You.

Nodejs (Express) connecting MySQL - Local and Remote connection different?

guys. I am learning how to use Express to connect to remote MySQL. So, I started out doing it on my local machine (a local MySQL server). After I have succeeded on the local environment, I tried changing the the connection to a remote MySQL hosting (at DB4Free). Yes, I have succeeded on the localhost. However, whenever I run a Get/Post to the remote MySQL Server, my console show me the error below. I'll attach the related segment of codes below here. I have been trying it the whole afternoon.
Hope that someone here can enlighten on this matter. Thank you in advance guys :)
This is the error shown in my console
My file for connecting db is as below - ConnectionString.js
var mysql = require("mysql");
var pool = mysql.createPool({
connectionLimit : 100,
host : '85.10.205.173:3306',
user : '******* ',
password : '*******',
database : '*******',
});
exports.getConnection = function(callback) {
pool.getConnection(function(err, conn) {
if(err) {
return callback(err);
}
callback(err, conn);
});
};
Portion of my file for the routes and query is this
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var conn = require('../database/ConnectionString');
var result;
//Validate user login
router.get('/login', function(req, res, next) {
conn.getConnection(
function (err, client) {
client.query('SELECT * FROM mt_User', function(err, rows) {
// And done with the connection.
if(err){
console.log('Query Error');
}
res.json(rows);
client.release();
// Don't use the connection here, it has been returned to the pool.
});
});
});
Alright, I have found the issue. It seems that the mysql package in npm requires that the host and port to be defined separately. After tuning it to this code below for my ConnectionString.js file. It finally works.
var mysql = require("mysql");
var pool = mysql.createPool({
connectionLimit : 100,
host : '85.10.205.173',
port : 3306,
user : '*******',
password : '*******',
database : '*******',
});
exports.getConnection = function(callback) {
pool.getConnection(function(err, conn) {
if(err) {
return callback(err);
}
callback(err, conn);
});
};

establishing a connection to database using environment variables

I'm creating an API for my app that fetches some data from my amazon db.
I have added environment variables to a custom.sh file in profile.d on my server. The weird thing is, I can print out those variables from my api, but the only variable that works when creating the connection is the user variable.
When I hard code the database credentials in the connection string it works just fine.
here is my custom.sh where I declare the environment variables
#custom environment variables, with the actual values removed
export DB_HOST=value1;
export DB_PASS=value2;
export DB_USER=value3;
export DB_NAME=value4;
here is my nodejs expressjs api file
var express = require('express');
var app = express();
var mysql = require('mysql');
var DB_HOST = formatEnvironmentVariable(process.env.DB_HOST);
var DB_USER = formatEnvironmentVariable(process.env.DB_USER);
var DB_PASS = formatEnvironmentVariable(process.env.DB_PASS);
var DB_NAME = "'"+process.env.DB_NAME+"'";
function formatEnvironmentVariable(env) {
env = "'"+env+"'";
return env
}
var pool = mysql.createPool({
host : DB_HOST,
user : DB_USER,
password : DB_PASS,
database : DB_NAME,
connectionLimit: 100,
debug: false
})
function QueryTheDatabase(req, res, querystring) {
pool.getConnection(function(err,connection){
if (err) {
connection.release();
res.json({"code" : 100, "status" : "Error in connection database"});
return;
}
console.log('connected as id ' + connection.threadId);
connection.query(querystring,function(err,rows){
connection.release();
console.log("error? "+err);
if(!err) {
res.json(rows);
}
});
connection.on('error', function(err) {
console.log("error");
res.json({"code" : 100, "status" : "Error in connection database"});
return;
});
});
}
app.get('theurl', function(req, res) {
QueryTheDatabase(req, res, "the query that works fine");
});
var server = app.listen(3000, function () {
var host = server.address().address;
var host = server.address().port;
});
I'm not exactly sure why only the DB_USER variable is set properly (it may be that some other process is sending that information). If you're running your shell script as such:
$ ./custom.sh
It won't work. It's essentially creating a sub-shell and the exported variables are local to that shell (they won't affect the parent)
The only way to make environment variables accessible to your node process would be to source the file first.
$ source ./custom.sh
I got it to work finally, turns out I didnt need to add ' ' with my format function.
instead of
var DB_HOST = formatEnvironmentVariable(process.env.DB_HOST);
var DB_USER = formatEnvironmentVariable(process.env.DB_USER);
var DB_PASS = formatEnvironmentVariable(process.env.DB_PASS);
var DB_NAME = "'"+process.env.DB_NAME+"'";
I wrote
var DB_HOST = process.env.DB_HOST;
var DB_USER = process.env.DB_USER;
var DB_PASS = process.env.DB_PASS;
var DB_NAME = process.env.DB_NAME;
For this I'll suggest To use
config npm
https://www.npmjs.com/package/config