mirror of
https://github.com/whyour/qinglong.git
synced 2026-10-16 22:35:32 +08:00
115 lines
3.9 KiB
JavaScript
115 lines
3.9 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const os = require('node:os');
|
|
const { promisify } = require('node:util');
|
|
const { execFile } = require('node:child_process');
|
|
const grpc = require('@grpc/grpc-js');
|
|
const loader = require('@grpc/proto-loader');
|
|
const load = require('../helpers/load-security-module.cjs');
|
|
const run = promisify(execFile);
|
|
|
|
test('JS and Python script reports reach the same authenticated RPC with bounded failure', async (t) => {
|
|
const data = fs.mkdtempSync(path.join(os.tmpdir(), 'ql-audit-rpc-'));
|
|
t.after(() => fs.rmSync(data, { recursive: true, force: true }));
|
|
fs.mkdirSync(path.join(data, 'config'));
|
|
const certs = await load('back/config/grpcCerts.ts', {
|
|
'./index': { configPath: path.join(data, 'config') },
|
|
'./util': { fileExist: async (p) => fs.existsSync(p) },
|
|
'../loaders/logger': { info() {}, error() {} },
|
|
}).initGrpcCerts();
|
|
const definition = loader.loadSync(path.resolve('back/protos/api.proto'), {
|
|
keepCase: true,
|
|
defaults: true,
|
|
});
|
|
const Api = grpc.loadPackageDefinition(definition).com.ql.api.Api;
|
|
const received = [];
|
|
const server = new grpc.Server();
|
|
server.addService(Api.service, {
|
|
RecordNotifyLog: (call, callback) => {
|
|
received.push(call.request);
|
|
callback(null, { code: 200 });
|
|
},
|
|
});
|
|
const credentials = grpc.ServerCredentials.createSsl(
|
|
Buffer.from(certs.caCert),
|
|
[
|
|
{
|
|
private_key: Buffer.from(certs.serverKey),
|
|
cert_chain: Buffer.from(certs.serverCert),
|
|
},
|
|
],
|
|
true,
|
|
);
|
|
const port = await new Promise((resolve, reject) =>
|
|
server.bindAsync('127.0.0.1:0', credentials, (error, port) =>
|
|
error ? reject(error) : resolve(port),
|
|
),
|
|
);
|
|
t.after(() => server.forceShutdown());
|
|
const env = {
|
|
...process.env,
|
|
QL_DIR: process.cwd(),
|
|
QL_DATA_DIR: data,
|
|
GRPC_PORT: String(port),
|
|
ID: '9',
|
|
HITOKOTO: 'false',
|
|
};
|
|
await run(
|
|
process.execPath,
|
|
[
|
|
'-e',
|
|
`require('./shell/preload/notificationAudit.js')({title:'JS task',content:'body',success:true,notifyType:'smtp',scriptName:'task.js',taskId:process.env.ID})`,
|
|
],
|
|
{ env, timeout: 8000 },
|
|
);
|
|
const python = `import importlib.util,sys,types,smtplib,os
|
|
sys.modules['requests']=types.SimpleNamespace()
|
|
spec=importlib.util.spec_from_file_location('notify',os.path.join(os.environ['QL_DIR'],'sample/notify.py'))
|
|
n=importlib.util.module_from_spec(spec);spec.loader.exec_module(n)
|
|
class Mail:
|
|
def __init__(self,*a,**kw): pass
|
|
def login(self,*a): pass
|
|
def sendmail(self,*a): return {}
|
|
def close(self): pass
|
|
smtplib.SMTP_SSL=Mail
|
|
n.push_config={'SMTP_SERVER':'fixture','SMTP_SSL':'true','SMTP_EMAIL':'sender@example.test','SMTP_PASSWORD':'private-password','SMTP_NAME':'fixture','HITOKOTO':False}
|
|
n.send('Python success','body')
|
|
def rejected(*a,**kw): raise RuntimeError('private-password')
|
|
smtplib.SMTP_SSL=rejected
|
|
n.send('Python failure','body')
|
|
`;
|
|
await run('python3', ['-c', python], { env, timeout: 12000 });
|
|
assert.deepEqual(
|
|
received.map((x) => [x.title, x.success]),
|
|
[
|
|
['JS task', true],
|
|
['Python success', true],
|
|
['Python failure', false],
|
|
],
|
|
);
|
|
assert.ok(received.every((x) => x.taskId === '9'));
|
|
assert.ok(!JSON.stringify(received).includes('private-password'));
|
|
// Missing certificates and an older/unavailable backend must not kill scripts.
|
|
await run(
|
|
process.execPath,
|
|
[
|
|
'-e',
|
|
`require('./shell/preload/notificationAudit.js')({title:'offline'}).then(()=>console.log('done'))`,
|
|
],
|
|
{ env: { ...env, QL_DATA_DIR: path.join(data, 'missing') }, timeout: 8000 },
|
|
);
|
|
server.forceShutdown();
|
|
const started = Date.now();
|
|
await run(
|
|
process.execPath,
|
|
[
|
|
'-e',
|
|
`require('./shell/preload/notificationAudit.js')({title:'offline'})`,
|
|
],
|
|
{ env, timeout: 8000 },
|
|
);
|
|
assert.ok(Date.now() - started < 5000);
|
|
});
|