feat: apply auth to container and cli client

This commit is contained in:
wancat committed 2023-09-12 00:12:09 +08:00
1 parent 030dc95e24
commit 0f53696f71
8 files changed
+64 -27

No files matched your search

+40 -3
View File
@@ -57,21 +57,29 @@ async function lastSession() {
return session return session
} }
async function connect(sessionId) { async function connect(sessionId, token) {
console.log(`Session ID: ${sessionId}`) console.log(`Session ID: ${sessionId}`)
console.log('Use Ctrl + D to exit.') console.log('Use Ctrl + D to exit.')
if (!sessionId) exit() if (!sessionId) exit()
const socket = io(program.opts().host, { const socket = io(program.opts().host, {
auth: {
token,
},
query: { query: {
session_id: sessionId, session_id: sessionId,
}, },
}) })
socket.on('open', function open() { socket.on('connection', function open() {
console.log('Connected to the server.') console.log('Connected to the server.')
}) })
socket.on('connect_error', (err) => {
console.error(err.message)
exit(1)
})
socket.on('message', console.log) socket.on('message', console.log)
socket.on('terminal', function incoming(data) { socket.on('terminal', function incoming(data) {
@@ -101,6 +109,26 @@ async function connect(sessionId) {
}) })
} }
async function login() {
try {
const res = await api.post('/login/password', {
username: program.opts().user,
password: program.opts().password,
})
const { token } = res.data
if (!token) {
console.error(res.data)
exit(1)
}
console.log('Login success.')
return token
} catch (err) {
console.error(err.message)
exit(1)
return null
}
}
async function main() { async function main() {
api = axios.create({ api = axios.create({
baseURL: `${program.opts().host}/api/v1`, baseURL: `${program.opts().host}/api/v1`,
@@ -111,18 +139,27 @@ async function main() {
console.log(program.opts().session) console.log(program.opts().session)
// main() // main()
const token = await login()
api.defaults.headers.common.Authorization = `Bearer ${token}`
const sessionId = const sessionId =
program.opts().session || program.opts().session ||
(program.opts().create ? (await createSession())._id : null) || (program.opts().create ? (await createSession())._id : null) ||
(await lastSession())._id (await lastSession())._id
await connect(sessionId) await connect(sessionId, token)
} }
program program
.option('-s, --session <string>', 'Session ID') .option('-s, --session <string>', 'Session ID')
.option('-c, --create', 'Create a new session') .option('-c, --create', 'Create a new session')
.option('-d, --debug', 'Debug mode') .option('-d, --debug', 'Debug mode')
.option('-u, --user <string>', 'Username', get('USERNAME', 'testUser'))
.option(
'-p, --password <string>',
'Password',
get('PASSWORD', 'testPassword')
)
.option( .option(
'-h, --host <string>', '-h, --host <string>',
'Server host', 'Server host',
+1 -1
View File
@@ -49,7 +49,6 @@ async function main() {
output, output,
error, error,
exit_code: CMD_EXIT_CODE, exit_code: CMD_EXIT_CODE,
token: TOKEN,
pwd: PWD, pwd: PWD,
...additionalData, ...additionalData,
} }
@@ -58,6 +57,7 @@ async function main() {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization: `Bearer ${TOKEN}`,
}, },
body: JSON.stringify(payload), body: JSON.stringify(payload),
}) })
@@ -1,26 +1,18 @@
/* eslint-disable import/prefer-default-export */ /* eslint-disable import/prefer-default-export */
import Command from '../../models/command.js' import Command from '../../models/command.js'
import Session from '../../models/session.js' import Session from '../../models/session.js'
import { verifySessionJWT } from '../../utils/auth.js'
import CommandHandler from '../../game/commandHandler.js' import CommandHandler from '../../game/commandHandler.js'
export async function newCommand(req, res) { export async function newCommand(req, res) {
console.log('new command:', req.body) console.log('new command:', req.body)
const { token, command, pwd, output, error, ...additionalData } = req.body const { command, pwd, output, error, ...additionalData } = req.body
if (!command) { if (!command) {
res.status(400).json({ message: 'command is required' }) res.status(400).json({ message: 'command is required' })
return return
} }
let sessionId const sessionId = req.user.session_id
try {
const decoded = await verifySessionJWT(token)
sessionId = decoded.session_id
} catch (err) {
res.status(401).json({ message: 'token not valid' })
return
}
const session = await Session.findById(sessionId) const session = await Session.findById(sessionId)
@@ -5,7 +5,7 @@ import SessionHandler from '../../game/sessionHandler.js'
export async function getSessionList(req, res) { export async function getSessionList(req, res) {
try { try {
const query = { user: req.user.id } const query = { user: req.user._id }
if (req.query.quest_id) { if (req.query.quest_id) {
query.quest = req.query.quest_id query.quest = req.query.quest_id
} }
@@ -70,7 +70,7 @@ export async function getSessionById(req, res) {
try { try {
const session = await Session.findOne({ const session = await Session.findOne({
_id: req.params.id, _id: req.params.id,
user: req.user.id, user: req.user._id,
}) })
if (!session) { if (!session) {
@@ -88,7 +88,7 @@ export async function deleteSessionById(req, res) {
try { try {
const session = await Session.findOneAndDelete({ const session = await Session.findOneAndDelete({
_id: req.params.id, _id: req.params.id,
user: req.user.id, user: req.user._id,
}) })
if (!session) { if (!session) {
+2 -2
View File
@@ -1,13 +1,13 @@
import { Router } from 'express' import { Router } from 'express'
import passport from 'passport' import passport from 'passport'
import { genJwt } from '../../utils/auth.js' import { genJWT } from '../../utils/auth.js'
const router = Router() const router = Router()
async function issueToken(req, res) { async function issueToken(req, res) {
const { user } = req const { user } = req
const token = await genJwt({ const token = await genJWT({
_id: user.id, _id: user.id,
username: user.username, username: user.username,
email: user.email, email: user.email,
+11 -3
View File
@@ -1,7 +1,7 @@
import { Server } from 'socket.io' import { Server } from 'socket.io'
import { getAndStartContainer, attachContainer } from '../containers/docker.js' import { getAndStartContainer, attachContainer } from '../containers/docker.js'
import Session from '../models/session.js' import Session from '../models/session.js'
import { defaultUser, genSessionJWT } from '../utils/auth.js' import { genJWT, verifyJWT } from '../utils/auth.js'
const sessions = new Map() const sessions = new Map()
@@ -45,7 +45,9 @@ async function connectClient(socket) {
return return
} }
const token = await genSessionJWT(session) const token = await genJWT({
session_id: session.id,
})
let container let container
let stream let stream
@@ -90,8 +92,14 @@ export default (server) => {
io.use(async (socket, next) => { io.use(async (socket, next) => {
console.log('Authenticating...') console.log('Authenticating...')
try { try {
const user = await defaultUser() const { token } = socket.handshake.auth
if (!token) {
next(new Error('Token not found.'))
return
}
const user = await verifyJWT(token)
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
console.log(user)
socket.user = user socket.user = user
next() next()
} catch (err) { } catch (err) {
+1 -1
View File
@@ -27,7 +27,7 @@ export async function defaultUser() {
return user return user
} }
export function genJwt(payload) { export function genJWT(payload) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
jwt.sign( jwt.sign(
payload, payload,
+4 -4
View File
@@ -303,6 +303,10 @@ paths:
/commands: /commands:
post: post:
summary: Record a command that was executed in a session summary: Record a command that was executed in a session
tags:
- signed-in
security:
- BearerAuth: []
requestBody: requestBody:
required: true required: true
content: content:
@@ -433,13 +437,9 @@ components:
Command: Command:
type: object type: object
required: required:
- token
- pwd - pwd
- command - command
properties: properties:
token:
type: string
description: The JWT token of the session
pwd: pwd:
type: string type: string
example: '/root' example: '/root'