@gadmin2n/schematics 0.0.117 → 0.0.119
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/application/files/gadmin2-game-angle-demo/age-sops-guides.md +219 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/gitignore +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/main.ts +3 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Age + SOPS 使用指引(.env)
|
|
2
|
+
|
|
3
|
+
## 目标
|
|
4
|
+
|
|
5
|
+
使用 Age + SOPS 对 `.env` 加密,Git 中仅保存 `.env.enc`。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
``` bash
|
|
10
|
+
brew install age sops
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
| 平台 | age | SOPS |
|
|
14
|
+
| --------------- | ---------------------- | ------------------------ |
|
|
15
|
+
| macOS | `brew install age` | `brew install sops` |
|
|
16
|
+
| Ubuntu / Debian | `sudo apt install age` | 下载官方 Release(二进制) |
|
|
17
|
+
| Rocky / CentOS | `sudo dnf install age` | 下载官方 Release(二进制) |
|
|
18
|
+
| Alpine | `apk add age` | `apk add sops` |
|
|
19
|
+
| Docker | `apt install age` | 下载官方 Release(二进制) |
|
|
20
|
+
| GitHub Actions | `apt install age` | `getsops/sops-installer` |
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## 生成密钥(每人独立)
|
|
24
|
+
|
|
25
|
+
每位团队成员在自己的机器上生成专属密钥:
|
|
26
|
+
|
|
27
|
+
``` bash
|
|
28
|
+
age-keygen -o key.txt
|
|
29
|
+
mkdir -p ~/.config/sops/age
|
|
30
|
+
mv key.txt ~/.config/sops/age/keys.txt
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
> 私钥只存在于本机,**绝不共享、绝不上传**。
|
|
34
|
+
|
|
35
|
+
将自己的**公钥**(`# public key:` 那一行)告知团队( 就是放入`.sops.yaml`,放在项目根目录)
|
|
36
|
+
|
|
37
|
+
## 创建 `.sops.yaml`(多收件人)
|
|
38
|
+
|
|
39
|
+
将所有团队成员的公钥列入,SOPS 加密时会同时为每个人加密,每人用自己的私钥均可解密:
|
|
40
|
+
|
|
41
|
+
``` yaml
|
|
42
|
+
creation_rules:
|
|
43
|
+
- path_regex: .*\.env$
|
|
44
|
+
age: >-
|
|
45
|
+
age1alice_PUBLIC_KEY,
|
|
46
|
+
age1bob_PUBLIC_KEY,
|
|
47
|
+
age1charlie_PUBLIC_KEY
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
> `.sops.yaml` **提交进 Git**,公钥可以公开。
|
|
51
|
+
|
|
52
|
+
### 人员变更
|
|
53
|
+
|
|
54
|
+
**新人加入:** 将其公钥追加到 `.sops.yaml`,然后执行:
|
|
55
|
+
``` bash
|
|
56
|
+
sops updatekeys .env.enc
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**人员离职:** 从 `.sops.yaml` 删除其公钥,同样执行 `sops updatekeys .env.enc`。其旧私钥立即失去解密能力,无需重新分发任何密钥。
|
|
60
|
+
|
|
61
|
+
## 首次加密
|
|
62
|
+
|
|
63
|
+
``` bash
|
|
64
|
+
vi .env
|
|
65
|
+
sops encrypt .env > .env.enc
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 修改
|
|
69
|
+
|
|
70
|
+
``` bash
|
|
71
|
+
sops .env.enc
|
|
72
|
+
```
|
|
73
|
+
> 会自动用vi/vim打开,编辑完自动加密,不需要手工:`decrypt -> edit -> encrypt`
|
|
74
|
+
|
|
75
|
+
## 本地运行
|
|
76
|
+
|
|
77
|
+
### 方法一:生成临时 .env
|
|
78
|
+
|
|
79
|
+
``` bash
|
|
80
|
+
sops -d .env.enc > .env
|
|
81
|
+
node server.js
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
> 需要严格禁止Coding agent访问 `.env` 文件
|
|
85
|
+
|
|
86
|
+
### 方法二:导入环境变量
|
|
87
|
+
|
|
88
|
+
``` bash
|
|
89
|
+
set -a
|
|
90
|
+
source <(sops -d .env.enc)
|
|
91
|
+
set +a
|
|
92
|
+
node server.js
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
应用继续使用:
|
|
96
|
+
|
|
97
|
+
``` js
|
|
98
|
+
process.env.XXX
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 准备部署专用密钥
|
|
102
|
+
|
|
103
|
+
部署环境使用独立的 deploy key,**不使用任何个人私钥**,避免人员变更影响部署。
|
|
104
|
+
|
|
105
|
+
``` bash
|
|
106
|
+
# 生成 deploy key(在本地安全环境执行)
|
|
107
|
+
age-keygen -o deploy-key.txt
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
将 deploy key 的公钥加入 `.sops.yaml`,然后重新加密:
|
|
111
|
+
|
|
112
|
+
``` bash
|
|
113
|
+
sops updatekeys .env.enc
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
> `deploy-key.txt` 私钥只上传到部署平台的 Secrets,不提交 Git,本地用完可删除。
|
|
117
|
+
|
|
118
|
+
## 部署(VM / Linux)
|
|
119
|
+
|
|
120
|
+
将 deploy 私钥放置:
|
|
121
|
+
|
|
122
|
+
``` text
|
|
123
|
+
/etc/sops/key.txt
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
设置权限:
|
|
127
|
+
|
|
128
|
+
``` bash
|
|
129
|
+
chmod 600 /etc/sops/key.txt
|
|
130
|
+
export SOPS_AGE_KEY_FILE=/etc/sops/key.txt
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
启动:
|
|
134
|
+
|
|
135
|
+
``` bash
|
|
136
|
+
sops -d .env.enc > .env
|
|
137
|
+
exec node server.js
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Kubernetes 部署
|
|
141
|
+
|
|
142
|
+
### 创建 Secret
|
|
143
|
+
|
|
144
|
+
``` bash
|
|
145
|
+
kubectl create secret generic sops-age-key \
|
|
146
|
+
--from-file=key.txt=deploy-key.txt
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Deployment
|
|
150
|
+
|
|
151
|
+
将 Secret 以 volume 挂载,通过 entrypoint 脚本启动:
|
|
152
|
+
|
|
153
|
+
``` sh
|
|
154
|
+
#!/bin/sh
|
|
155
|
+
set -e
|
|
156
|
+
|
|
157
|
+
export SOPS_AGE_KEY_FILE=/etc/sops/key.txt
|
|
158
|
+
sops -d /app/.env.enc > /app/.env
|
|
159
|
+
|
|
160
|
+
exec node server.js
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Dockerfile:
|
|
164
|
+
|
|
165
|
+
``` dockerfile
|
|
166
|
+
ENTRYPOINT ["/app/entrypoint.sh"]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
相关 Deployment yaml 片段:
|
|
170
|
+
|
|
171
|
+
``` yaml
|
|
172
|
+
volumes:
|
|
173
|
+
- name: sops-age-key
|
|
174
|
+
secret:
|
|
175
|
+
secretName: sops-age-key
|
|
176
|
+
containers:
|
|
177
|
+
- name: app
|
|
178
|
+
volumeMounts:
|
|
179
|
+
- name: sops-age-key
|
|
180
|
+
mountPath: /etc/sops
|
|
181
|
+
readOnly: true
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## GitHub Actions 部署
|
|
185
|
+
|
|
186
|
+
将 deploy 私钥内容存入 GitHub Secrets(如 `SOPS_AGE_KEY`),在 workflow 中使用:
|
|
187
|
+
|
|
188
|
+
``` yaml
|
|
189
|
+
- name: Decrypt .env
|
|
190
|
+
run: |
|
|
191
|
+
echo "${{ secrets.SOPS_AGE_KEY }}" > /tmp/age-key.txt
|
|
192
|
+
export SOPS_AGE_KEY_FILE=/tmp/age-key.txt
|
|
193
|
+
sops -d .env.enc > .env
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Git 建议
|
|
197
|
+
|
|
198
|
+
提交:
|
|
199
|
+
|
|
200
|
+
- `.env.enc`
|
|
201
|
+
- `.sops.yaml`
|
|
202
|
+
|
|
203
|
+
不要提交:
|
|
204
|
+
|
|
205
|
+
- `.env`
|
|
206
|
+
- `keys.txt`
|
|
207
|
+
|
|
208
|
+
`.gitignore`
|
|
209
|
+
|
|
210
|
+
``` gitignore
|
|
211
|
+
.env
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 最佳实践
|
|
215
|
+
|
|
216
|
+
- 一个环境一个 `.env.enc`
|
|
217
|
+
- 私钥绝不进入 Git
|
|
218
|
+
- 业务代码始终通过 `process.env` 读取配置
|
|
219
|
+
- 部署时解密,运行结束后如无需要可删除 `.env`
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import './lib/tracing'; // OpenTelemetry Prisma instrumentation - 必须第一个导入
|
|
2
2
|
|
|
3
|
+
// 非终端环境禁用 ANSI 颜色,避免日志收集时出现裸转义码
|
|
4
|
+
if (!process.stdout.isTTY) process.env.NO_COLOR = '1';
|
|
5
|
+
|
|
3
6
|
import { AllExceptionsFilter, UserType } from '@gadmin2n/nest-common';
|
|
4
7
|
import {
|
|
5
8
|
ClassSerializerInterceptor,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"@dnd-kit/modifiers": "^9.0.0",
|
|
11
11
|
"@dnd-kit/sortable": "^7.0.2",
|
|
12
12
|
"@dnd-kit/utilities": "^3.2.2",
|
|
13
|
-
"@gadmin2n/charts": "
|
|
13
|
+
"@gadmin2n/charts": "0.0.10",
|
|
14
14
|
"@gadmin2n/react-common": "^0.0.70",
|
|
15
15
|
"@monaco-editor/react": "^4.7.0",
|
|
16
16
|
"@refinedev/antd": "^5.47.0",
|