mirror of
https://github.com/hardenedlinux/harbian-audit.git
synced 2025-07-05 12:54:55 +02:00
add nodejs+redis+mysql usecase
This commit is contained in:
parent
788e14357f
commit
7f542415fc
243
docs/examples/test-cases/nodejs-redis-mysql-usecase/README.md
Normal file
243
docs/examples/test-cases/nodejs-redis-mysql-usecase/README.md
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
# Nodejs + redis + mysql demo
|
||||||
|
## environment
|
||||||
|
* OS: Debian
|
||||||
|
* Nodejs: 10.13.0
|
||||||
|
* MySQL: 10.1.26-MariaDB-0+deb9u1
|
||||||
|
* Redis: 5.0.1
|
||||||
|
* Kernel: linux-image-4.12.0-grsec-evil191
|
||||||
|
### Install packages
|
||||||
|
|
||||||
|
#### Install mysql
|
||||||
|
|
||||||
|
```
|
||||||
|
apt install mysql-server
|
||||||
|
```
|
||||||
|
#### Configurate database
|
||||||
|
|
||||||
|
Create helloworld database
|
||||||
|
|
||||||
|
```
|
||||||
|
mysql -uroot
|
||||||
|
MariaDB [(none)]> CREATE DATABASE helloworld;
|
||||||
|
```
|
||||||
|
Grant proper access to the helloworld database:
|
||||||
|
|
||||||
|
```
|
||||||
|
MariaDB [(none)]> GRANT ALL PRIVILEGES ON helloworld.* TO 'helloworld'@'localhost' \
|
||||||
|
IDENTIFIED BY 'HELLOWORLD_DBPASS';
|
||||||
|
MariaDB [(none)]> GRANT ALL PRIVILEGES ON helloworld.* TO 'helloworld'@'%' \
|
||||||
|
IDENTIFIED BY 'HELLOWORLD_DBPASS';
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace HEllOWORLD_DBPASS with a suitable password.
|
||||||
|
|
||||||
|
|
||||||
|
#### Install Redis
|
||||||
|
|
||||||
|
edit `/etc/apt/source.list` and add `stretch-backports` source
|
||||||
|
|
||||||
|
```
|
||||||
|
deb http://mirrors.163.com/debian/ stretch-backports main
|
||||||
|
deb-src http://mirrors.163.com/debian/ stretch-backports main
|
||||||
|
```
|
||||||
|
and update
|
||||||
|
|
||||||
|
```
|
||||||
|
apt update
|
||||||
|
```
|
||||||
|
install the package
|
||||||
|
```
|
||||||
|
apt -t stretch-backports install redis-server
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Configurate Redis
|
||||||
|
|
||||||
|
modify `/etc/redis/redis.conf`, changce supervised no to
|
||||||
|
|
||||||
|
```
|
||||||
|
supervised systemd
|
||||||
|
```
|
||||||
|
|
||||||
|
Configuring a Redis Password
|
||||||
|
modify /etc/redis/redis.conf you can find the
|
||||||
|
```
|
||||||
|
# requirepass foobared
|
||||||
|
```
|
||||||
|
|
||||||
|
uncommnet it and change foobared to a suitable password
|
||||||
|
|
||||||
|
for example, you can gener:
|
||||||
|
|
||||||
|
```
|
||||||
|
openssl rand 60 | openssl base64 -A
|
||||||
|
|
||||||
|
jkO663LT4SLU522cIBaMrWshaEEP+67oRGIdDV3AEpIaS7IQ9yYWP78nmruBFM2cPdxSudvrrmlZeKil
|
||||||
|
```
|
||||||
|
|
||||||
|
systemctl restart redis
|
||||||
|
|
||||||
|
#### Install Nodejs
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
#as root
|
||||||
|
apt install curl -y
|
||||||
|
curl -sL https://deb.nodesource.com/setup_10.x | bash -
|
||||||
|
apt-get install -y nodejs
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Install pax-bites
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
cat <<EOF > debian_auto_deploy.sh
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
WORKDIR=/tmp/debian-grsec-configs
|
||||||
|
mkdir -p $WORKDIR
|
||||||
|
cd $WORKDIR
|
||||||
|
|
||||||
|
echo "###########################################################################"
|
||||||
|
echo -e "[+] \e[93mInstalling paxctl-ng/elfix...\e[0m"
|
||||||
|
echo "----------------------------------------------"
|
||||||
|
apt-get install -y vim libc6-dev libelf-dev libattr1-dev build-essential git
|
||||||
|
wget https://dev.gentoo.org/%7Eblueness/elfix/elfix-0.9.2.tar.gz && tar zxvf elfix-0.9.2.tar.gz
|
||||||
|
cd elfix-0.9.2
|
||||||
|
|
||||||
|
./configure --enable-ptpax --enable-xtpax --disable-tests
|
||||||
|
make && make install
|
||||||
|
cd $WORKDIR
|
||||||
|
|
||||||
|
echo "###########################################################################"
|
||||||
|
echo -e "[+] \e[93mDeploying configs....\e[0m"
|
||||||
|
echo "----------------------------------------------"
|
||||||
|
|
||||||
|
echo 'DPkg::Post-Invoke {"/bin/bash /usr/sbin/pax-bites.sh -e /etc/pax_flags_debian.config"; };' >77pax-bites
|
||||||
|
|
||||||
|
cp 77pax-bites /etc/apt/apt.conf.d/
|
||||||
|
wget https://github.com/hardenedlinux/hardenedlinux_profiles/raw/master/debian/pax_flags_debian.config
|
||||||
|
cp pax_flags_debian.config /etc/
|
||||||
|
|
||||||
|
echo "###########################################################################"
|
||||||
|
echo -e "[+] \e[93mDeploying pax-bites...\e[0m"
|
||||||
|
echo "----------------------------------------------"
|
||||||
|
git clone https://github.com/hardenedlinux/pax-bites.git
|
||||||
|
cp pax-bites/pax-bites.sh /usr/sbin/
|
||||||
|
pax-bites.sh -e /etc/pax_flags_debian.config
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
run command:
|
||||||
|
|
||||||
|
```
|
||||||
|
bash debian_auto_deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
after install paxctl and pax-bites
|
||||||
|
|
||||||
|
we should modify `/etc/pax_flags_debian.config`
|
||||||
|
|
||||||
|
add following content:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Nodejs
|
||||||
|
/usr/bin/node;m
|
||||||
|
```
|
||||||
|
`-m` means `disable MPROTECT`
|
||||||
|
|
||||||
|
for more details you can check it from `paxctl-ng`
|
||||||
|
|
||||||
|
perform change
|
||||||
|
|
||||||
|
```
|
||||||
|
pax-bites.sh -e /etc/pax_flags_debian.config
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Add new user for helloworld service
|
||||||
|
|
||||||
|
adduser helloworld
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Using helloworld to install the dependencies.
|
||||||
|
|
||||||
|
unzip the helloworld.zip
|
||||||
|
|
||||||
|
```
|
||||||
|
//Installation all dependencies:
|
||||||
|
# su helloworld
|
||||||
|
$ unzip helloworld.zip
|
||||||
|
$ cd helloworld
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### modify the config file locate in `config/config.js`
|
||||||
|
|
||||||
|
you can setup the mysql and redis
|
||||||
|
|
||||||
|
```
|
||||||
|
BASE_DIR = __dirname;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
port: 3000,
|
||||||
|
//mysql
|
||||||
|
mysql: {
|
||||||
|
host: 'localhost',
|
||||||
|
user: 'helloworld',
|
||||||
|
password: 'HELLOWORLD_DBPASS',
|
||||||
|
connectionLimit: 10,
|
||||||
|
charset: 'utf8mb4',
|
||||||
|
},
|
||||||
|
database: 'helloworld',
|
||||||
|
//redis
|
||||||
|
redis: {
|
||||||
|
tokenName: 'helloworld',
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: 6379,
|
||||||
|
password: 'jkO663LT4SLU522cIBaMrWshaEEP+67oRGIdDV3AEpIaS7IQ9yYWP78nmruBFM2cPdxSudvrrmlZeKil',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
//Installation PM2:
|
||||||
|
```
|
||||||
|
# npm install pm2 -g
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ su helloworld
|
||||||
|
$ export NODE_ENV=production && pm2 start ./app.js --name helloworld
|
||||||
|
$ pm2 startup systemd
|
||||||
|
|
||||||
|
[PM2] Init System found: systemd
|
||||||
|
[PM2] To setup the Startup Script, copy/paste the following command:
|
||||||
|
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u helloworld --hp /home/helloworld
|
||||||
|
```
|
||||||
|
change to root user and execute
|
||||||
|
|
||||||
|
```
|
||||||
|
# env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u helloworld --hp /home/helloworld
|
||||||
|
```
|
||||||
|
|
||||||
|
and switch back to `helloworld` user
|
||||||
|
|
||||||
|
```
|
||||||
|
$ pm2 save
|
||||||
|
```
|
||||||
|
now start the service
|
||||||
|
|
||||||
|
```
|
||||||
|
# systemctl start pm2-helloworld
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Open up http://{your server ip}:3000,then you can see the helloworld page.
|
||||||
|
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
https://nodejs.org/en/
|
||||||
|
https://www.mysql.com/
|
||||||
|
http://pm2.keymetrics.io/
|
||||||
|
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-debian-9
|
BIN
docs/examples/test-cases/nodejs-redis-mysql-usecase/helloworld/.DS_Store
vendored
Normal file
BIN
docs/examples/test-cases/nodejs-redis-mysql-usecase/helloworld/.DS_Store
vendored
Normal file
Binary file not shown.
@ -0,0 +1,22 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const sql = require('./services/SqlService');
|
||||||
|
const myredis = require('./services/RedisService');
|
||||||
|
const { database, redis, port } = require('./config/config');
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
app.get('/', async (req, res) => {
|
||||||
|
//data from mysql
|
||||||
|
let data_mysql = await sql.query(`select content from ${database}.test limit 1`);
|
||||||
|
//data from redis
|
||||||
|
let data_redis = await myredis.get(redis.tokenName);
|
||||||
|
res.send(`
|
||||||
|
Hello World!<br/><br/>
|
||||||
|
<span style="width:160px;font-weight:bold;display:inline-block;">Data from mysql</span> ${data_mysql[0]['content']}<br/><br/>
|
||||||
|
<span style="width:160px;font-weight:bold;display:inline-block;">Data from redis</span> ${data_redis}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(port, function () {
|
||||||
|
console.log('Hello world run on port 3000!');
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,21 @@
|
|||||||
|
BASE_DIR = __dirname;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
port: 3000,
|
||||||
|
//mysql
|
||||||
|
mysql: {
|
||||||
|
host: 'localhost',
|
||||||
|
user: 'YOUR_MYSQL_USER',
|
||||||
|
password: 'YOUR_MYSQL_PASSWORD',
|
||||||
|
connectionLimit: 10,
|
||||||
|
charset: 'utf8mb4',
|
||||||
|
},
|
||||||
|
database: 'helloworld',
|
||||||
|
//redis
|
||||||
|
redis: {
|
||||||
|
tokenName: 'helloworld',
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: 6379,
|
||||||
|
password: 'YOUR_REDIS_PASSWORD',
|
||||||
|
},
|
||||||
|
}
|
2774
docs/examples/test-cases/nodejs-redis-mysql-usecase/helloworld/package-lock.json
generated
Normal file
2774
docs/examples/test-cases/nodejs-redis-mysql-usecase/helloworld/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "helloworld",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "This is helloworld project",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "nodemon ./app.js"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"log4js": "^3.0.6",
|
||||||
|
"mysql": "^2.15.0",
|
||||||
|
"redis": "^2.8.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.15.4",
|
||||||
|
"nodemon": "^1.18.6"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
const log4js = require('log4js');
|
||||||
|
log4js.configure({
|
||||||
|
appenders: { helloworld: { type: 'file', filename: 'helloworld.log' } },
|
||||||
|
categories: { default: { appenders: ['helloworld'], level: 'debug' } },
|
||||||
|
pm2: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const logger = log4js.getLogger('helloworld');
|
||||||
|
|
||||||
|
module.exports = logger;
|
@ -0,0 +1,68 @@
|
|||||||
|
const redis = require("redis")
|
||||||
|
const logger = require('./LogService')
|
||||||
|
const config = require('../config/config')
|
||||||
|
|
||||||
|
class RedisService {
|
||||||
|
constructor() {
|
||||||
|
this.client = null
|
||||||
|
this.init()
|
||||||
|
this.set(config.redis.tokenName, 'hello,i am data from redis')
|
||||||
|
}
|
||||||
|
|
||||||
|
//redis service init
|
||||||
|
init() {
|
||||||
|
let option = {}
|
||||||
|
option['host'] = config.redis.host
|
||||||
|
option['port'] = config.redis.port
|
||||||
|
if (config.redis.password) {
|
||||||
|
option['password'] = config.redis.password
|
||||||
|
}
|
||||||
|
this.client = redis.createClient(option)
|
||||||
|
|
||||||
|
this.client.on("error", function (err) {
|
||||||
|
console.log('Redis connect fail!')
|
||||||
|
logger.info(err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get value
|
||||||
|
* redis.get('tokens','object') / redis.get('tokens')
|
||||||
|
*/
|
||||||
|
get(key, type) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.client.get(key, (err, reply) => {
|
||||||
|
if (err) {
|
||||||
|
logger.info(err)
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
if (type === 'object') {
|
||||||
|
resolve(JSON.parse(reply))
|
||||||
|
} else {
|
||||||
|
resolve(reply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
/*
|
||||||
|
* set value
|
||||||
|
* redis.set('tokens',tokens,'object') / redis.set('tokens',tokens)
|
||||||
|
*/
|
||||||
|
set(key, value, type) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.client.set(key, (type === 'object' ? JSON.stringify(value) : value), (err, reply) => {
|
||||||
|
if (err) {
|
||||||
|
logger.info(err)
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve(reply)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new RedisService()
|
@ -0,0 +1,89 @@
|
|||||||
|
const mysql = require('mysql');
|
||||||
|
const logger = require('./LogService');
|
||||||
|
const config = require('../config/config');
|
||||||
|
const { database } = config;
|
||||||
|
|
||||||
|
class SqlService {
|
||||||
|
constructor() {
|
||||||
|
this.connection = {};
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
//mysql service init
|
||||||
|
async init() {
|
||||||
|
let mysqlConfig, pool;
|
||||||
|
mysqlConfig = Object.assign({}, config.mysql);
|
||||||
|
pool = mysql.createPool(mysqlConfig);
|
||||||
|
this.connection.getConnection = (cb) => {
|
||||||
|
pool.getConnection((err, connection) => {
|
||||||
|
if (err) {
|
||||||
|
cb(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.info(`mysql connect success`);
|
||||||
|
cb(connection);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//if exist database
|
||||||
|
await this.init_database();
|
||||||
|
//if exist table
|
||||||
|
let querys = [
|
||||||
|
{
|
||||||
|
tableName: 'test',
|
||||||
|
sqls: [
|
||||||
|
{ sql: "CREATE TABLE IF NOT EXISTS " + `${database}.test` + " (`id` int(11) NOT NULL AUTO_INCREMENT,`content` text NOT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;", params: [] },
|
||||||
|
{ sql: `insert into ${database}.test(content) values(?)`, params: ['hello,i am data from mysql'] },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
await this.init_tables(querys);
|
||||||
|
}
|
||||||
|
|
||||||
|
//init database
|
||||||
|
async init_database() {
|
||||||
|
await this.query(`CREATE DATABASE IF NOT EXISTS ${database} DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;`);
|
||||||
|
}
|
||||||
|
|
||||||
|
//init tables
|
||||||
|
async init_tables(data) {
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
let { tableName, sqls } = data[i];
|
||||||
|
let isExist;
|
||||||
|
try {
|
||||||
|
isExist = await this.query(`select count(*) from ${database}.${tableName}`);
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isExist) {
|
||||||
|
logger.info(`Table ${tableName} is not existed~`);
|
||||||
|
for (let j = 0; j < sqls.length; j++) {
|
||||||
|
await this.query(sqls[j]['sql'], sqls[j]['params']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mysql single query
|
||||||
|
query(sql, params) {
|
||||||
|
logger.info(sql)
|
||||||
|
logger.info(params)
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
return this.connection.getConnection((connection) => {
|
||||||
|
connection.query(sql, params ? params : [], (error, result) => {
|
||||||
|
if (error) {
|
||||||
|
//release connection
|
||||||
|
connection.release()
|
||||||
|
logger.info(error)
|
||||||
|
reject(error)
|
||||||
|
} else {
|
||||||
|
//release connection
|
||||||
|
connection.release()
|
||||||
|
resolve(result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new SqlService()
|
Loading…
x
Reference in New Issue
Block a user