Skip to content

Commit

Permalink
feat: 新增审计系统 (#782)
Browse files Browse the repository at this point in the history
## 改动

scow节点新增audit-server服务

1. 新增audit-server服务,供portal-web和mis-web调用记录日志和查看日志功能
2. 新增audit-db服务,供audit-server服务储存和查看操作日志


![image](https://github.com/PKUHPC/SCOW/assets/130351655/bac72a8c-7506-4b0b-87e1-0e8e1f10485f)


数据库信息
databaseName: scow_audit
tableName:  operation_log
table desc:


![image](https://github.com/PKUHPC/SCOW/assets/130351655/4462b6cc-e81b-4704-a76f-a6e3bd9f1ce7)


其中metaData里根据每种操作类型的不同,以json形式储存了不同的字段,供操作内容展示。

3. scow-cli增加以上服务部署,在/config/audit.yaml中配置是否部署此服务以及该服务的db和url
```yaml
# 审计服务的url,默认不修改
url: audit-server:5000

# 审计系统数据库的信息
db:
  host: audit-db
  port: 3306
  user: root
  dbName: scow-audit

```

4. mis-web在用户空间,账户管理,租户管理,平台管理各增加操作日志页面,其中的展示逻辑如
4.1 用户空间展示的是所有operatorUserId 等于该用户的操作日志
4.2 账户管理展示的是所有保存了targetAccountName且与该账户名相等的操作日志
4.3 租户管理展示的是该租户下所有用户和operatorUserId相等的操作日志
4.4 平台管理展示的是所有操作日志
4.5 所有页面可筛选操作行为,操作时间,操作结果, 账户租户和平台的操作日志还能搜索操作者。
4.6 如果没有配置审计系统,则操作日志路由不展示。门户系统和管理系统将不会记录操作日志。


![image](https://github.com/PKUHPC/SCOW/assets/130351655/67c45329-21ec-405d-91f4-3eb5290e9977)


![image](https://github.com/PKUHPC/SCOW/assets/130351655/77b238dd-933e-4a6c-a27f-121c9c0b093b)

关于操作行为的枚举以及对应的操作码和操作详情展示格式记录在该文档附录:

https://jgf29kqp7z.feishu.cn/wiki/G30hwOvOJiJhWIk3mxIcen2snUe

ps: 是否需要新增一篇blog 通知用户该新功能改动?
  • Loading branch information
ZihanChen821 authored Aug 28, 2023
1 parent ffefb17 commit ee89b11
Show file tree
Hide file tree
Showing 129 changed files with 3,850 additions and 188 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-seals-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@scow/grpc-api": minor
---

新增审计系统,增加 CreateOperationLog 和 GetOperationLogs 接口定义
5 changes: 5 additions & 0 deletions .changeset/cool-tomatoes-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@scow/config": minor
---

新增审计系统配置文件
12 changes: 12 additions & 0 deletions .changeset/dirty-stingrays-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@scow/lib-operation-log": minor
"@scow/audit-server": minor
"@scow/protos": minor
"@scow/portal-web": minor
"@scow/demo-vagrant": minor
"@scow/mis-web": minor
"@scow/cli": minor
"@scow/docs": minor
---

新增审计系统服务,记录门户系统及管理系统操作日志及展示
2 changes: 1 addition & 1 deletion .github/workflows/test-build-publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
- name: Upload test converage
uses: codecov/codecov-action@v3
with:
files: ./libs/auth/coverage/lcov.info,./libs/ssh/coverage/lcov.info,./libs/libconfig/coverage/lcov.info,./libs/decimal/coverage/lcov.info,./libs/server/coverage/lcov.info,./apps/cli/coverage/lcov.info,./apps/auth/coverage/lcov.info,./apps/mis-server/coverage/lcov.info,./apps/portal-server/coverage/lcov.info,./apps/gateway/coverage/lcov.info
files: ./libs/auth/coverage/lcov.info,./libs/ssh/coverage/lcov.info,./libs/libconfig/coverage/lcov.info,./libs/decimal/coverage/lcov.info,./libs/server/coverage/lcov.info,./apps/cli/coverage/lcov.info,./apps/auth/coverage/lcov.info,./apps/mis-server/coverage/lcov.info,./apps/portal-server/coverage/lcov.info,./apps/gateway/coverage/lcov.info,./apps/audit-server/coverage/lcov.info

- name: Create Release Pull Request or Publish
id: changesets
Expand Down
1 change: 1 addition & 0 deletions apps/audit-server/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# @scow/audit-server
1 change: 1 addition & 0 deletions apps/audit-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# 审计系统
8 changes: 8 additions & 0 deletions apps/audit-server/config/audit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
db:
host: localhost
port: 3306
user: root
password: mysqlrootpassword
dbName: scow_audit


2 changes: 2 additions & 0 deletions apps/audit-server/env/.env.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DB_HOST=localhost
DB_NAME=scow_audit
4 changes: 4 additions & 0 deletions apps/audit-server/env/.env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
LOG_LEVEL=error
PORT=0
DB_HOST=localhost
DB_NAME=scow_audit_${JEST_WORKER_ID}
35 changes: 35 additions & 0 deletions apps/audit-server/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright (c) 2022 Peking University and Peking University Institute for Computing and Digital Economy
* SCOW is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

// jest.config.js
const { pathsToModuleNameMapper } = require("ts-jest");
// In the following statement, replace `./tsconfig` with the path to your `tsconfig` file
// which contains the path mapping (ie the `compilerOptions.paths` option):
const { compilerOptions } = require("./tsconfig");

const dotenv = require("dotenv");

dotenv.config({ path: "env/.env.test" });

/** @type {import('@jest/types').Config.InitialOptions} */
module.exports = {
rootDir: ".",
preset: "ts-jest",
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: "<rootDir>/" }),
testMatch: [
"<rootDir>/tests/**/*.test.ts?(x)",
],
coverageDirectory: "coverage",
testTimeout: 30000,
coverageReporters: ["lcov"],
setupFilesAfterEnv: ["jest-extended/all"],
};
54 changes: 54 additions & 0 deletions apps/audit-server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "@scow/audit-server",
"version": "1.0.0",
"description": "",
"private": true,
"main": "build/index.js",
"scripts": {
"dev": "dotenv -e env/.env.dev -- node --watch -r ts-node/register -r tsconfig-paths/register src/index.ts",
"build": "rimraf build && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
"serve": "node build/index.js",
"test": "jest",
"orm": "dotenv -e env/.env.dev -- npx mikro-orm"
},
"files": [
"scripts",
"build",
".npmrc",
"!**/*.map"
],
"keywords": [],
"author": "PKUHPC (https://github.com/PKUHPC)",
"license": "Mulan PSL v2",
"repository": "https://github.com/PKUHPC/SCOW",
"dependencies": {
"@ddadaal/tsgrpc-server": "0.19.4",
"@ddadaal/tsgrpc-common": "0.2.4",
"@ddadaal/tsgrpc-client": "0.17.6",
"@grpc/grpc-js": "1.8.21",
"@mikro-orm/cli": "5.7.14",
"@mikro-orm/core": "5.7.14",
"@mikro-orm/migrations": "5.7.14",
"@mikro-orm/mysql": "5.7.14",
"@scow/config": "workspace:*",
"@scow/lib-config": "workspace:*",
"@scow/lib-decimal": "workspace:*",
"@scow/utils": "workspace:*",
"@scow/protos": "workspace:*",
"pino": "8.15.0",
"pino-pretty": "10.2.0"
},
"devDependencies": {
"@types/google-protobuf": "3.15.6"
},
"mikro-orm": {
"useTsNode": true,
"configPaths": [
"./src/mikro-orm.config.ts",
"./src/mikro-orm.config.js"
]
},
"volta": {
"extends": "../../package.json"
}
}
39 changes: 39 additions & 0 deletions apps/audit-server/src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Copyright (c) 2022 Peking University and Peking University Institute for Computing and Digital Economy
* SCOW is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

import { Server } from "@ddadaal/tsgrpc-server";
import { omitConfigSpec } from "@scow/lib-config";
import { readVersionFile } from "@scow/utils/build/version";
import { config } from "src/config/env";
import { plugins } from "src/plugins";
import { operationLogServiceServer } from "src/services/operationLog";
import { logger } from "src/utils/logger";

export async function createServer() {

const server = new Server({
host: config.HOST,
port: config.PORT,

logger,
});

server.logger.info({ version: readVersionFile() }, "@scow/audit-server: ");
server.logger.info({ config: omitConfigSpec(config) }, "Loaded env config");

for (const plugin of plugins) {
await server.register(plugin);
}
await server.register(operationLogServiceServer);

return server;
}
18 changes: 18 additions & 0 deletions apps/audit-server/src/config/audit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright (c) 2022 Peking University and Peking University Institute for Computing and Digital Economy
* SCOW is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

import { getAuditConfig } from "@scow/config/build/audit";
import { logger } from "src/utils/logger";

export const auditConfig = getAuditConfig(undefined, logger);


27 changes: 27 additions & 0 deletions apps/audit-server/src/config/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Copyright (c) 2022 Peking University and Peking University Institute for Computing and Digital Economy
* SCOW is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

import { bool, envConfig, host, port, str } from "@scow/lib-config";

export const config = envConfig({
HOST: host({ default: "0.0.0.0", desc: "监听地址" }),
PORT: port({ default: 5000, desc: "监听端口" }),
LOG_LEVEL: str({
default: "info",
desc: "日志等级",
}),
LOG_PRETTY: bool({ desc: "以可读的方式输出log", default: false }),

DB_NAME: str({ desc: "存放系统数据的数据库名,将会覆写配置文件。用于测试", default: undefined }),
DB_PASSWORD: str({ desc: "审计系统数据库密码,将会覆写配置文件", default: undefined }),
});

63 changes: 63 additions & 0 deletions apps/audit-server/src/entities/OperationLog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright (c) 2022 Peking University and Peking University Institute for Computing and Digital Economy
* SCOW is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

import { Entity, Enum, PrimaryKey, Property } from "@mikro-orm/core";
import { CURRENT_TIMESTAMP, DATETIME_TYPE } from "src/utils/orm";

export enum OperationResult {
UNKNOWN = "UNKNOWN",
SUCCESS = "SUCCESS",
FAIL = "FAIL",
}

@Entity()
export class OperationLog {
@PrimaryKey()
id!: number;

@Property()
operatorUserId!: string;

@Property()
operatorIp!: string;

@Property({ columnType: DATETIME_TYPE, defaultRaw: CURRENT_TIMESTAMP })
operationTime?: Date;

@Enum({ items: () => OperationResult, comment: Object.values(OperationResult).join(", ") })
operationResult: OperationResult;

@Property({ type: "json", nullable: true })
metaData?: { [key: string]: any; };

constructor(init: {
operationLogId?: number;
operatorUserId: string;
operatorIp: string;
operationTime?: Date;
operationResult: OperationResult;
metaData: { [key: string]: any };
}) {
if (init.operationLogId) {
this.id = init.operationLogId;
}
this.operatorUserId = init.operatorUserId;
this.operatorIp = init.operatorIp;
if (init.operationTime) {
this.operationTime = init.operationTime;
}
this.operationResult = init.operationResult;
this.metaData = init.metaData;
}

}

17 changes: 17 additions & 0 deletions apps/audit-server/src/entities/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Copyright (c) 2022 Peking University and Peking University Institute for Computing and Digital Economy
* SCOW is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

import { OperationLog } from "src/entities/OperationLog";

export const entities = [
OperationLog,
];
44 changes: 44 additions & 0 deletions apps/audit-server/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright (c) 2022 Peking University and Peking University Institute for Computing and Digital Economy
* SCOW is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

import { createServer } from "src/app";
import { migrationUp } from "src/tasks/migrationUp";

async function main() {

const server = await createServer();

const args = process.argv.slice(1);

// run tasks
if (args.length > 1) {
const [_scriptName, command] = args;

const logger = server.logger.child({ task: command });

switch (command) {

case "migrationUp":
await migrationUp(server.ext.orm);
break;
default:
logger.error("Unexpected task name %s", command);
process.exit(1);
}

process.exit(0);
}

await server.start();
}

main();
Loading

0 comments on commit ee89b11

Please sign in to comment.