Compare commits

...

663 Commits

Author SHA1 Message Date
fit2bot
c8eb7cccb1 perf: Modify error message for desktop client login 2024-07-31 10:58:08 +08:00
wangruidong
001828fb2b fix: stop job failed 2024-07-30 18:49:17 +08:00
feng
d0e355a86d perf: When account push change secret windows only modify the type equal to password 2024-07-30 18:33:19 +08:00
wangruidong
4a5f327498 fix: Arbitrary File Read in Ansible Play 2024-07-30 18:15:37 +08:00
Eric
04761a9373 perf: Check if CORE_HOST should ignore SSL 2024-07-30 16:55:04 +08:00
feng
077731a4b4 perf: Saml2 callback url miss port 2024-07-26 18:14:04 +08:00
feng
75e79efa5f perf: The locked IP shows the username + translate 2024-07-17 18:10:42 +08:00
fit2bot
ca5ffb6278 fix: session viewset api permission validation (#13749)
* fix: session viewset api permission validation

* fix: some api permission validation

---------

Co-authored-by: Bai <baijiangjie@gmail.com>
2024-07-17 15:36:10 +08:00
wangruidong
c7e149f15d fix: 在线同步获取不到资产问题 2024-07-17 15:35:59 +08:00
feng
60ac5ddaf2 perf: Dashboard user login statistics issue 2024-07-17 14:57:30 +08:00
feng
244407b212 perf: Translate 2024-07-17 11:37:42 +08:00
Bai
f08f01fe49 fix: authentication passkey model migrations 2024-07-17 10:41:14 +08:00
fit2bot
b2f11bbbf3 perf: Migrate (#13742)
Co-authored-by: feng <1304903146@qq.com>
2024-07-17 10:24:19 +08:00
Bai
6108a09089 fix: i18n error 2024-07-17 10:00:50 +08:00
Bai
93cf58ca76 fix: i18n error 2024-07-17 09:53:39 +08:00
feng
587c49082f perf: Notification remove kael magnus 2024-07-16 19:33:50 +08:00
fit2bot
50090c5310 perf: Translate (#13732)
Co-authored-by: feng <1304903146@qq.com>
2024-07-16 19:02:49 +08:00
吴小白
b4182a0d1c fix: deploy applet host 2024-07-16 12:49:04 +08:00
wangruidong
8a2d7b69fa perf: 社区版移除magnus 2024-07-16 10:41:45 +08:00
fit2bot
84821e97f4 perf: Community supports custom platforms (#13720)
Co-authored-by: feng <1304903146@qq.com>
2024-07-15 17:32:03 +08:00
fit2bot
e0f20ce047 perf: Translate (#13717)
Co-authored-by: feng <1304903146@qq.com>
2024-07-15 17:06:30 +08:00
ibuler
375f60fef8 perf: community add postgre support 2024-07-15 16:19:03 +08:00
fit2bot
ced79ea6c9 perf: ConnectionTokenSerializer add org_name label (#13714)
Co-authored-by: feng <1304903146@qq.com>
2024-07-15 14:33:40 +08:00
吴小白
2d4b9ff5a8 perf: remove receptor 2024-07-12 18:38:45 +08:00
wangruidong
0a5467886a fix: creat linux asset protocol default value is sftp 2024-07-09 19:04:31 +08:00
吴小白
9809415f78 fix: FromAsCasing keywords 2024-07-09 10:36:18 +08:00
Bryan
02fc045370 Merge pull request #13600 from jumpserver/dev
v4.0.0
2024-07-03 19:04:35 +08:00
maninhill
7ee7d50f22 chore: Update README.md 2024-07-03 18:54:56 +08:00
fit2bot
3d015398c3 perf: Luna translate (#13599)
Co-authored-by: feng <1304903146@qq.com>
2024-07-03 17:50:55 +08:00
wangruidong
da8b328f80 fix: bulk delete playbook 500 error 2024-07-03 17:15:50 +08:00
fit2bot
82a6702c90 perf: Translate (#13594)
Co-authored-by: feng <1304903146@qq.com>
2024-07-03 16:50:09 +08:00
fit2bot
ad267bcd35 perf: Translate (#13593)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-07-03 16:42:02 +08:00
maninhill
15dc922bca chore: Update README.md 2024-07-03 16:10:03 +08:00
Aaron3S
22405d46d6 feat: add chen translate 2024-07-03 15:54:19 +08:00
wangruidong
35b0741068 fix: modify render_to_json rbac 2024-07-03 15:53:25 +08:00
刘瑞斌
d7b8174fd0 chore: use unseq list 2024-07-03 15:35:14 +08:00
ibuler
43cfb11bca perf: tag export format use name:value style 2024-07-03 15:34:53 +08:00
wangruidong
f955cebaa0 perf: Translate 2024-07-03 15:17:10 +08:00
fit2bot
5d7ec054e6 perf: Community limit (#13584)
Co-authored-by: feng <1304903146@qq.com>
2024-07-03 15:01:37 +08:00
Bryan
6088a38eed Update README.md 2024-07-03 14:51:51 +08:00
fit2bot
e1a84e76bb perf: some translation (#13585)
* perf: applet host platform

* perf: some translation

---------

Co-authored-by: ibuler <ibuler@qq.com>
2024-07-03 14:51:21 +08:00
wangruidong
19f9179e7f perf: update migrations same with v3 2024-07-03 14:46:17 +08:00
Bryan
aa4a8d5b42 Update README.md 2024-07-03 14:44:28 +08:00
老广
10ba31086c Update README.md 2024-07-03 14:40:49 +08:00
fit2bot
fa8312bc65 perf: Translate (#13575)
Co-authored-by: feng <1304903146@qq.com>
2024-07-02 18:30:23 +08:00
maninhill
512e727dd4 chore: Update CONTRIBUTING.md 2024-07-02 18:25:57 +08:00
wangruidong
a529609275 fix: Resolve issue with update permissions preventing data import 2024-07-02 16:34:10 +08:00
fit2bot
a8973330fe fix: Account tempale cannot push params (#13571)
Co-authored-by: feng <1304903146@qq.com>
2024-07-02 16:12:27 +08:00
ibuler
d42acc3848 perf: applet host platform 2024-07-02 15:15:13 +08:00
fit2bot
912cefbc85 perf: Lina LoginLogTotal translate (#13569)
Co-authored-by: feng <1304903146@qq.com>
2024-07-02 15:10:33 +08:00
feng
2bb475d0ce perf: Account push log optimization 2024-07-02 14:55:38 +08:00
ibuler
22788ff2da perf: remove org api scope 2024-07-02 14:11:16 +08:00
fit2bot
5594b25ae0 perf: Login confirm return failed (#13560)
Co-authored-by: feng <1304903146@qq.com>
2024-07-02 11:02:30 +08:00
Aaron3S
4733d89807 perf: 优化 chen 翻译 2024-07-02 10:19:36 +08:00
wangruidong
c718fe1a9d perf: modify user login ACL msg 2024-07-01 19:30:42 +08:00
wangruidong
237b4a82c9 fix: handle 500 error when re-binding DingTalk user to another user 2024-07-01 18:03:47 +08:00
fit2bot
76e0cbb8ac perf: update lion i18n (#13556)
* perf: update lion i18n

* perf: update i18n

---------

Co-authored-by: Eric <xplzv@126.com>
2024-07-01 16:22:46 +08:00
fit2bot
b3a670d380 perf: Lina mfa translate (#13555)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-07-01 16:12:13 +08:00
wangruidong
db243d050e fix: playbook FileNotFoundError 2024-07-01 15:51:14 +08:00
wangruidong
cd2648291e perf: Translate 2024-07-01 15:15:53 +08:00
wangruidong
4a49bde1f0 perf: add compatibility for macOS environment 2024-07-01 15:02:32 +08:00
wangruidong
d9754496d0 perf: add bubblewrap 2024-07-01 15:02:32 +08:00
fit2bot
6753b5fd19 perf: Translate (#13550)
Co-authored-by: feng <1304903146@qq.com>
2024-07-01 11:42:33 +08:00
fit2bot
aeb320ba30 perf: Lina translate (#13548)
Co-authored-by: feng <1304903146@qq.com>
2024-07-01 10:15:06 +08:00
ibuler
e712e8ccfc perf: ansible version and set user lang 2024-06-28 18:59:44 +08:00
fit2bot
1d6f827296 perf: Migrate (#13540)
Co-authored-by: feng <1304903146@qq.com>
2024-06-28 18:36:24 +08:00
ibuler
772c9b385c perf: lang setting from core 2024-06-28 16:40:25 +08:00
wangruidong
f5053728e7 perf: Translate Tags 2024-06-28 15:28:57 +08:00
wangruidong
f67fd29499 perf: Community update user list API to exclude specific fields 2024-06-28 14:54:07 +08:00
fit2bot
138ea35620 fix: Got perm tree 500 (#13533)
Co-authored-by: feng <1304903146@qq.com>
2024-06-28 11:39:09 +08:00
wangruidong
bf56549f01 perf: Task log optimize 2024-06-28 10:25:10 +08:00
Eric
908181af64 perf: clean mp4 replay file
perf: refactor code to clean files
2024-06-27 18:12:37 +08:00
fit2bot
7b4d3c44f8 fix: Asset perm calculate failed (#13530)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-06-27 18:05:08 +08:00
feng
b7a6454d65 fix: Asset perm calculate failed 2024-06-27 17:56:41 +08:00
ibuler
6d81fa7fdf perf: change default login title 2024-06-27 17:55:57 +08:00
wangruidong
0e8833cce3 perf: Translate Client connection 2024-06-27 11:27:43 +08:00
fit2bot
24d9e65532 fix: Asset 003 migrate failed (#13519)
Co-authored-by: feng <1304903146@qq.com>
2024-06-26 21:42:43 +08:00
ibuler
bca9bdf619 perf: translate some word 2024-06-26 19:29:56 +08:00
fit2bot
cd39e20808 perf: Applet host provider add filterset (#13517)
Co-authored-by: feng <1304903146@qq.com>
2024-06-26 19:07:28 +08:00
fit2bot
9c8680d3f4 perf: Translate (#13514)
Co-authored-by: feng <1304903146@qq.com>
2024-06-26 17:06:23 +08:00
wangruidong
dd84ca8f85 fix: Virtualapp rbac config 2024-06-26 16:43:32 +08:00
Eric
96c1f689c0 perf: modify dbeave remoteapp dislay name 2024-06-26 16:19:09 +08:00
wangruidong
84855bfd7e perf: Translate Lark 2024-06-26 16:13:16 +08:00
fit2bot
40c5a218a9 perf: Translate (#13509)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-06-26 15:18:37 +08:00
wangruidong
8e87972a76 perf: Translate ticket action 2024-06-26 14:37:32 +08:00
fit2bot
3faee9b80c perf: change some translate (#13505)
* perf: some word translate


---------

Co-authored-by: ibuler <ibuler@qq.com>
2024-06-25 19:36:35 +08:00
fit2bot
5a1389a187 perf: Translate (#13504)
Co-authored-by: feng <1304903146@qq.com>
2024-06-25 19:10:32 +08:00
Eric
565c2f493c perf: add lion i18n 2024-06-25 19:04:40 +08:00
Bai
8d48593fc4 perf: Update README 2024-06-25 16:44:00 +08:00
fit2bot
b50c96fcd6 perf: Update README (#13497)
* perf: Update README

* perf: Update README

* perf: Update README

---------

Co-authored-by: Bai <baijiangjie@gmail.com>
2024-06-25 16:29:14 +08:00
ibuler
85700a2a26 perf: some word translate 2024-06-25 15:36:25 +08:00
Bryan
66615b7dd3 Update README.md 2024-06-25 15:34:31 +08:00
Bryan
2c1a1fa31e Update README.md 2024-06-25 15:34:31 +08:00
wangruidong
bbc442b56e perf: Translate CanDragSelect tips 2024-06-25 15:31:30 +08:00
Bryan
1ca579f4f0 Update README.md 2024-06-25 15:01:47 +08:00
Bryan
9e3b23179c Update README.md 2024-06-25 15:01:47 +08:00
Bryan
9fd861d047 Update README.md 2024-06-25 15:01:47 +08:00
fit2bot
4abfcb27d1 perf: Update README (#13491)
* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

---------

Co-authored-by: Bai <baijiangjie@gmail.com>
Co-authored-by: Bryan <jiangjie.bai@fit2cloud.com>
2024-06-25 11:22:38 +08:00
老广
3463761693 Update README.md 2024-06-25 10:28:14 +08:00
Eric
c311adc1da chore: update mysqlclient 2.2.4 2024-06-24 20:12:09 +08:00
ibuler
ee258707c8 perf: change initial passwd to ChangeMe 2024-06-24 20:11:49 +08:00
Eric
17d96669fe perf: remove pymysql 2024-06-24 20:11:23 +08:00
fit2bot
3fade107d5 perf: Translate (#13489)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-06-24 20:10:34 +08:00
wangruidong
f91ec6fa6a perf: favor & disfavor trans 2024-06-24 19:38:19 +08:00
Bai
dfff41e9d6 perf: Update README 2024-06-24 19:25:41 +08:00
Bai
478e81b8fa perf: Update README 2024-06-24 19:25:41 +08:00
wangruidong
9b14f2aa1f perf: ftp log has_file trans 2024-06-24 19:18:26 +08:00
Bryan
18e648af6e Update README.md (#13481)
* Update README.md

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README

* perf: Update README
2024-06-24 19:16:30 +08:00
老广
45bd69585a Update README.md 2024-06-24 18:24:21 +08:00
maninhill
42a0cde450 chore: Update README.md 2024-06-24 18:22:38 +08:00
Bai
a9ef21ea3f fix: poetry lock 2024-06-24 17:07:34 +08:00
Bai
13d24a12db fix: i18n messages 2024-06-24 17:07:34 +08:00
wangruidong
2bd09f246d fix: raise http 400 when batch delete in component settings 2024-06-24 16:25:54 +08:00
fit2bot
23c81cf5eb perf: Migrate asset dameng json (#13477)
Co-authored-by: feng <1304903146@qq.com>
2024-06-24 16:24:40 +08:00
Bryan
e95284335e Merge pull request #13472 from jumpserver/v4
Merge v4 to dev
2024-06-24 15:50:29 +08:00
Bai
1c7f82e65a Merge v4 to dev (Update poetry lock) 2024-06-24 15:47:13 +08:00
Bai
dfde50c768 Merge v4 to dev 2024-06-24 15:43:40 +08:00
ibuler
8bfbebf29e Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-06-24 14:51:42 +08:00
ibuler
8157f9891f perf: 优化批量删除判断 2024-06-24 14:50:53 +08:00
wangruidong
ad95adc833 perf: trans LDAP msg 2024-06-24 14:24:06 +08:00
ibuler
f7e55c9b89 merge: with remote 2024-06-24 11:06:32 +08:00
ibuler
11b125655d perf: passkey help msg 2024-06-24 11:05:41 +08:00
fit2bot
c6628a1959 perf: Translate (#13471)
Co-authored-by: feng <1304903146@qq.com>
2024-06-24 10:57:10 +08:00
fit2bot
165d030c8e perf: ansible runner in isolated mode (#13434)
perf: use new ansible runner

perf: change lock

Co-authored-by: ibuler <ibuler@qq.com>
2024-06-24 10:21:31 +08:00
feng
9be77cf58f perf: Ansible inventory set jms 2024-06-24 10:15:05 +08:00
吴小白
887724bad4 feat: upgrade poetry.lock 2024-06-24 10:11:49 +08:00
fit2bot
ae7dbbedcc perf: Edit rbac perms (#13468)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-06-21 19:08:37 +08:00
fit2bot
407a77f61b perf: trans StopLogOutput 2024-06-21 18:05:39 +08:00
fit2bot
e06f9a03d6 perf: System setting perm (#13463)
Co-authored-by: feng <1304903146@qq.com>
2024-06-20 19:19:14 +08:00
fit2bot
07edbea54e perf: Update ah translate (#13459)
Co-authored-by: feng <1304903146@qq.com>
2024-06-20 16:56:41 +08:00
ibuler
856e501a15 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-06-20 11:11:19 +08:00
ibuler
8cf900f9de perf: 生产授权树 2024-06-20 11:10:57 +08:00
fit2bot
a54605ac79 perf: Translate (#13454)
Co-authored-by: feng <1304903146@qq.com>
2024-06-19 19:36:47 +08:00
Bryan
e4ac73896f Merge pull request #13452 from jumpserver/dev
v3.10.11-lts
2024-06-19 16:01:26 +08:00
Bai
b283d88781 fix: Clone asset with accounts 2024-06-19 16:00:58 +08:00
wangruidong
92790d711e perf: Add log download button 2024-06-19 15:56:02 +08:00
gerry-fit
2977323800 perf: 登录重置密码传输进行加密 2024-06-19 14:53:50 +08:00
fit2bot
5b548d8d57 perf: Translate (#13450)
Co-authored-by: feng <1304903146@qq.com>
2024-06-19 14:48:48 +08:00
wangruidong
4a520e9e10 fix: 全局组织,添加标签报错 2024-06-19 09:27:03 +08:00
fit2bot
afdf777386 perf: Translate account (#13445)
Co-authored-by: feng <1304903146@qq.com>
2024-06-18 19:39:27 +08:00
ibuler
cd2af0dcf7 perf: english traslation 2024-06-18 18:47:06 +08:00
wangruidong
44f29e166c fix: 一些任务查找不到id和执行者 2024-06-18 16:52:18 +08:00
fit2bot
f42113afb9 fix: Fixed the issue of user login statistics (#13440)
Co-authored-by: feng <1304903146@qq.com>
2024-06-18 14:18:02 +08:00
Bai
523468f7af fix: Add API Exception traceback log if settings.DEBUG_DEV enabled 2024-06-18 11:58:44 +08:00
Bai
9385d04812 fix: Add API Exception traceback log if settings.DEBUG_DEV enabled 2024-06-18 11:55:56 +08:00
Bai
ff126f3459 fix: delete account error (DoesNotExist) 2024-06-18 11:06:40 +08:00
fit2bot
2ee435a8ec perf: Translate (#13438)
Co-authored-by: feng <1304903146@qq.com>
2024-06-17 19:47:05 +08:00
fit2bot
f3a827b76b perf: Translate (#13437)
Co-authored-by: feng <1304903146@qq.com>
2024-06-17 19:22:45 +08:00
fit2bot
50ceca9f06 perf: Perms system settings (#13435)
Co-authored-by: feng <1304903146@qq.com>
2024-06-17 17:40:03 +08:00
Bai
8a5e86dfa7 fix: migrations assets 0003 json.loads error 2024-06-17 10:39:38 +08:00
fit2bot
6ffae48ab2 perf: Translate (#13431)
Co-authored-by: feng <1304903146@qq.com>
2024-06-14 19:15:41 +08:00
wangruidong
66cd6e95a8 fix: 获取账号改密的任务列表超时 2024-06-14 18:54:01 +08:00
wangruidong
b28aec527f perf: 默认关闭作业中心 2024-06-14 18:18:35 +08:00
fit2bot
9ff78c8569 perf: Lina translate (#13427)
Co-authored-by: feng <1304903146@qq.com>
2024-06-14 15:16:00 +08:00
fit2bot
d6718d7b78 perf: Device asset remove_account_enabled false (#13426)
Co-authored-by: feng <1304903146@qq.com>
2024-06-14 14:47:13 +08:00
fit2bot
32966b260a perf: Refactor OperateLogStore separator logic for database compatibility (#13424)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-06-14 14:25:14 +08:00
feng
6c59888d77 perf: Refactor OperateLogStore separator logic for database compatibility 2024-06-14 14:09:53 +08:00
Bai
1c1d839b82 fix: i18n compilemessages 2024-06-14 09:53:08 +08:00
wangruidong
7d295cc675 perf: rbac applet modify translate 2024-06-13 18:26:10 +08:00
fit2bot
75496cbe91 perf: Account backup failed (#13420)
Co-authored-by: feng <1304903146@qq.com>
2024-06-13 18:20:00 +08:00
jiangweidong
496903dfb2 fix: 解决获取用户登录后端的session_key有两种的问题 2024-06-13 17:49:56 +08:00
wangruidong
11f6a029de perf: modify translate 2024-06-13 17:45:39 +08:00
Bai
e40c66c7ed fix: select_for_update error for out join sql 2024-06-13 15:50:11 +08:00
ibuler
2a33337963 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-06-13 13:04:07 +08:00
ibuler
bd1a768743 perf: change some translation 2024-06-13 13:02:03 +08:00
wangruidong
0a0312695b fix: es使用https报错 2024-06-13 10:33:47 +08:00
fit2bot
0c0ec098ae perf: Modify some translations (#13412)
Co-authored-by: wangruidong <940853815@qq.com>
2024-06-12 19:38:45 +08:00
fit2bot
37ad7b32e4 perf: Cloud account translate (#13413)
Co-authored-by: feng <1304903146@qq.com>
2024-06-12 19:38:07 +08:00
ibuler
2640963938 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-06-12 19:29:14 +08:00
ibuler
6bc9181c25 fix: some bugs 2024-06-12 19:25:36 +08:00
fit2bot
d8379195e6 perf: Platform automation add remove account method (#13411)
Co-authored-by: feng <1304903146@qq.com>
2024-06-12 19:23:40 +08:00
Bai
9195c658a0 perf: Update djangojs.po file 2024-06-12 18:36:04 +08:00
wangruidong
3fb261b5c8 fix: Role details - multiple instances of English in permissions list 2024-06-12 17:30:03 +08:00
ibuler
aa16c3d3a1 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-06-12 16:19:26 +08:00
ibuler
7be6cf2b73 perf: tags update 2024-06-12 16:19:16 +08:00
wangruidong
3608b025e5 fix: es8会话记录查询不到命令 2024-06-12 15:49:57 +08:00
fit2bot
60738da053 perf: Automation remove account task fail (#13406)
Co-authored-by: feng <1304903146@qq.com>
2024-06-12 15:30:52 +08:00
Aaron3S
507ad10389 feat: add some translations for chen 2024-06-12 15:27:53 +08:00
Bai
68244b2b37 perf: 更新 lock 文件 2024-06-12 14:30:37 +08:00
wangruidong
948e9ecb4b perf: 命令存储支持ES8的版本 2024-06-12 14:15:13 +08:00
wangruidong
67bc16238c perf: i18n 2024-06-12 10:25:22 +08:00
wangruidong
7ad4d9116a fix: LDAP定时同步任务设置多个通知人,消息内容分除第一个正常,其它人都不正常 2024-06-11 18:24:43 +08:00
Aaron3S
db88f6c9b4 perf: 优化 chen 翻译文件 2024-06-11 18:19:30 +08:00
fit2bot
8b7f60d43e fix: Cloud sync related issues (#13396)
Co-authored-by: feng <1304903146@qq.com>
2024-06-11 17:42:13 +08:00
wangruidong
9439035b86 fix: 账号备份,云同步定时任务不执行 2024-06-07 18:33:46 +08:00
halo
2b220d3753 perf: 去掉account序列化中params属性 2024-06-07 15:54:33 +08:00
ibuler
cd1f6a9137 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-06-06 16:56:47 +08:00
ibuler
7973d066a3 revert: asset permission real accounts serializer 2024-06-06 16:56:07 +08:00
Bai
440a7ae9cc perf: 添加配置项 FILE_UPLOAD_TEMP_DIR 2024-06-06 16:32:23 +08:00
wangruidong
ad65097a8f perf: Crontab i18n 2024-06-06 14:49:56 +08:00
ibuler
1b05f56598 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-06-05 19:34:04 +08:00
ibuler
3468f8cd40 perf: 修改授权的账号 2024-06-05 19:33:40 +08:00
Bryan
5c81e974cd Update README.md 2024-06-05 18:00:13 +08:00
Bryan
b638cf7417 Update README.md 2024-06-05 17:53:26 +08:00
Bryan
1db1961cc0 Update README.md 2024-06-05 17:25:45 +08:00
Bryan
811afdcf1a Update README.md 2024-06-05 17:25:12 +08:00
Bryan
1f87ce2a47 Update README.md 2024-06-05 17:09:04 +08:00
Bryan
8213e38e6a Update README.md 2024-06-05 17:01:31 +08:00
ibuler
263bcbb566 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-06-04 19:08:51 +08:00
ibuler
050ddc88f2 perf: labels 支持颜色 2024-06-04 19:08:16 +08:00
Bai
40a4efc992 fix: 修复用户登录报错刷新浏览器后依旧报错的问题(登录超时,请重新登录) 2024-06-04 16:33:06 +08:00
feng
38e8791d9f perf: Community Edition Remove db client 2024-06-04 16:24:37 +08:00
老广
15d4fafbdb chrome: change github action 2024-06-04 16:23:25 +08:00
fit2bot
deb8474c1b feat: add oracle database web-cli connect method (#13358)
Co-authored-by: Aaron3S <chenyang@fit2cloud.com>
2024-06-04 14:51:47 +08:00
fit2bot
12740ead08 perf: ticket translate (#13357)
Co-authored-by: feng <1304903146@qq.com>
2024-06-04 11:01:33 +08:00
Bai
6322559bd7 perf: i18n updated 2024-06-03 19:15:40 +08:00
Aaron3S
6c5eb00fb6 feat: 增加 chen 翻译文件 2024-06-03 16:42:23 +08:00
feng
dad2f8eb65 perf: koko translate 2024-06-03 14:29:57 +08:00
Bai
c8679f48f5 perf: Update i18n 2024-06-03 11:44:16 +08:00
fit2bot
510dc1eaf2 perf: translate (#13347)
Co-authored-by: feng <1304903146@qq.com>
2024-06-03 10:26:12 +08:00
wangruidong
a313753757 perf: action i18n 2024-05-31 16:34:03 +08:00
Gerry.tan
48b037ac26 feat: 支持 Dameng 数据库 2024-05-31 14:45:41 +08:00
wangruidong
53f106b30d perf: i18n 2024-05-31 14:39:56 +08:00
jiangweidong
dfd133cf5a perf: optimize user operation logs (#13221) 2024-05-31 11:05:35 +08:00
吴小白
0d27bfcfa9 perf: 添加 arm64 缺失依赖 2024-05-31 10:56:48 +08:00
jiangweidong
cdfb11549e fix: 解决OAuth2可以跳过不存在用户不允许登录的规则 2024-05-31 10:43:01 +08:00
wangruidong
ba6660216c perf: celery task log format 2024-05-31 10:15:11 +08:00
吴小白
3536af2051 perf: 按要求移除重复构建代码 2024-05-31 10:13:22 +08:00
fit2bot
21bb0a8162 fix: translate json (#13322)
Co-authored-by: feng <1304903146@qq.com>
2024-05-30 14:20:12 +08:00
jiangweidong
d718398791 feat: refactoring sync module (#13293) 2024-05-29 18:44:32 +08:00
fit2bot
0d825927e1 perf: Optimize GitHub labels and update related workflows (#13315)
* perf: Optimize GitHub labels and update related workflows

* perf: Optimize issue template

* perf: Optimize issue template

* Update 1_bug_report.yml

* Update 1_bug_report.yml

* Update 1_bug_report.yml

* Update 1_bug_report.yml

* Update 1_bug_report.yml

* Update 2_feature_request.yml

* Update 2_feature_request.yml

* Update 3_question.yml

* Update 3_question.yml

* Update 3_question.yml

* Update 1_bug_report.yml

* Update 2_feature_request.yml

* Update 1_bug_report_cn.yml

* Update 1_bug_report_cn.yml

* Update 2_feature_request_cn.yml

* Update 1_bug_report_cn.yml

* Update 1_bug_report_cn.yml

* Update 1_bug_report_cn.yml

* Update 3_question_cn.yml

* Update 1_bug_report_cn.yml

* Update 2_feature_request_cn.yml

* Update 3_question_cn.yml

* Update 2_feature_request_cn.yml

* Update 1_bug_report.yml

* Update 1_bug_report_cn.yml

* Update 2_feature_request.yml

* Update 3_question.yml

* perf: Optimize issue template

---------

Co-authored-by: Bai <baijiangjie@gmail.com>
Co-authored-by: Bryan <jiangjie.bai@fit2cloud.com>
2024-05-29 18:15:13 +08:00
吴小白
0b65e3ffda perf: 按要求移除重复构建代码 2024-05-28 18:50:11 +08:00
feng
91a1da57e9 perf: mfa interface optimization, mobile phone number can be empty 2024-05-28 17:27:17 +08:00
Bai
4e8d7df005 fix: v2->v3 The issue of authorized accounts displaying as empty when there are more than 10,000 authorization rules. 2024-05-28 16:09:12 +08:00
Bai
5d1829b998 fix: Disable the applet connection method when all applet hosts have is_active set to False 2024-05-28 11:07:40 +08:00
Bai
75df845024 perf: Remove dependency django-rest-swagger 2024-05-28 10:34:37 +08:00
Bai
c103253867 perf: perm tree search 2024-05-27 18:05:21 +08:00
ibuler
f95cbd6977 merge: with remote 2024-05-27 16:46:13 +08:00
ibuler
f16ec02c40 perf: 修改翻译 2024-05-27 16:43:26 +08:00
wangruidong
0ea2339ad5 perf: notification i18n 2024-05-27 15:24:31 +08:00
feng
81da9e018a fix: windows sync remove account fail and applet deploy rbac perm error and job exection log admin auditor cannot view 2024-05-27 11:41:30 +08:00
Bai
8ebdd59e00 Merge branch 'v4_bain' into v4 2024-05-27 11:35:16 +08:00
Bai
c4e30737a4 perf: i18n bai 2024-05-27 11:34:53 +08:00
ibuler
f127aca5f8 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-05-27 11:20:59 +08:00
ibuler
7333c8e094 perf: 修改 json 空格数量 2024-05-27 11:20:35 +08:00
Bai
a1e9382275 perf: i18n bai 2024-05-27 11:13:13 +08:00
ibuler
097a6c5c5f perf: 修改 label 为 tag 2024-05-27 11:07:36 +08:00
fit2bot
4e023057cc perf: ticket translate (#13291)
Co-authored-by: feng <1304903146@qq.com>
2024-05-27 11:00:54 +08:00
Bryan
7f90fccc4f perf: The label matching policy is configured with a random selection publisher 2024-05-27 10:26:35 +08:00
ibuler
4034e2152c Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-05-24 18:43:07 +08:00
ibuler
e8d6c6b711 merge: with remote 2024-05-24 18:42:37 +08:00
Bai
43215d27c5 perf: migrations i18n 2024-05-24 14:54:56 +08:00
Bai
e20db96331 Merge branch 'v4_baisse' into v4 2024-05-24 14:42:27 +08:00
Bai
564ad40b99 perf: i18n System Settings End 2024-05-24 14:41:28 +08:00
ibuler
32ef4c79da perf: 修改翻译 2024-05-23 19:00:28 +08:00
wangruidong
af4f6ebb26 perf: dashboard i18n 2024-05-23 18:23:10 +08:00
wangruidong
33b688b021 perf: modify task log i18n 2024-05-23 18:12:52 +08:00
fit2bot
b179770dbf perf: del extra translate (#13274)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-05-22 19:24:25 +08:00
Bai
e7f92ec0d7 merged: Merge to v4 (bai) 2024-05-22 18:12:35 +08:00
Bai
79449a8a02 perf: i18n System Settings -> Authentication-OIDC 2024-05-22 17:51:45 +08:00
fit2bot
4ebcba81e0 perf: dates_metrics api speed (#13266)
Co-authored-by: feng <1304903146@qq.com>
2024-05-22 15:25:38 +08:00
wangruidong
5616d31888 perf: CeleryTaskExecution保存时去掉无用参数 2024-05-22 14:04:11 +08:00
fit2bot
f259509ef8 fix: notification migrate file (#13269)
Co-authored-by: feng <1304903146@qq.com>
2024-05-22 10:47:55 +08:00
fit2bot
82977f9023 perf: tickets notifications add default data migrate file (#13268)
Co-authored-by: feng <1304903146@qq.com>
2024-05-21 19:24:26 +08:00
Bai
4a5205c5ac perf: i18n System Settings -> Features 2024-05-21 16:11:13 +08:00
ibuler
714b4ef7f4 merge: with remote 2024-05-21 14:47:37 +08:00
ibuler
df091f0ee1 perf: 添加 terminal 的 migrate 2024-05-21 14:44:48 +08:00
wangruidong
7037cf56ec perf: i18n 2024-05-21 10:47:15 +08:00
Eric
f683d195e4 perf: update lina i18n 2024-05-20 19:06:28 +08:00
Bai
5ab55b823c perf: i18n System Settings -> General,Org,Notifications 2024-05-20 18:39:57 +08:00
吴小白
0f2c769e8d Merge pull request #13255 from jumpserver/pr@v4@fix_docker_build
fix: 修正企业镜像缺失依赖
2024-05-20 15:02:56 +08:00
吴小白
1d53f292ae fix: 修正企业镜像缺失依赖 2024-05-20 14:57:15 +08:00
wangruidong
606d2c8933 fix: 关闭ssh client后,sftp,telnet不显示客户端连接方式 2024-05-20 10:02:12 +08:00
fit2bot
a15335cac9 perf: lina ja translate (#13252)
Co-authored-by: feng <1304903146@qq.com>
2024-05-17 18:46:30 +08:00
wangruidong
f33cf07859 perf: i18n 2024-05-17 18:30:19 +08:00
fit2bot
bce55421ce perf: MenuAccountTemplates zh translate (#13250)
Co-authored-by: feng <1304903146@qq.com>
2024-05-17 17:56:09 +08:00
fit2bot
c3449cd6bc perf: account translate (#13249)
Co-authored-by: feng <1304903146@qq.com>
2024-05-17 16:47:02 +08:00
ibuler
4e903ce19b Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-05-17 16:32:08 +08:00
ibuler
90826b358c perf: 修改翻译 2024-05-17 16:31:39 +08:00
吴小白
7d46aa9892 perf: 优化发布机部署 2024-05-17 15:22:16 +08:00
ibuler
49d2bd93b7 perf: merge with remote 2024-05-17 09:59:12 +08:00
ibuler
9f103a88d6 perf: 修改 org name 2024-05-17 09:58:12 +08:00
fit2bot
ce33bdc370 perf: account related translate (#13241)
Co-authored-by: feng <1304903146@qq.com>
2024-05-16 19:39:03 +08:00
fit2bot
cdf1f81c8a perf: account automation translate (#13240)
Co-authored-by: feng <1304903146@qq.com>
2024-05-16 19:12:24 +08:00
Eric
79edff5fca perf: 支持 loki log 2024-05-16 19:00:47 +08:00
Bryan
1518f792d6 Merge pull request #13236 from jumpserver/dev
v3.10.10-lts
2024-05-16 16:04:07 +08:00
feng
a534c496d0 perf: core celery always active 2024-05-16 15:52:11 +08:00
wangruidong
a11097fb5a fix: 定时任务,再次执行报错 2024-05-16 15:48:45 +08:00
feng
d4c1f93ef6 fix: send slack message failed 2024-05-16 15:23:31 +08:00
fit2bot
9168e92669 perf: update poetry lock (#13229)
Co-authored-by: feng <1304903146@qq.com>
2024-05-16 10:27:29 +08:00
fit2bot
a7316bc7c1 perf: translate (#13228)
Co-authored-by: feng <1304903146@qq.com>
2024-05-15 18:43:31 +08:00
fit2bot
bfd030d70f perf: upgrade jms-storage (#13223)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-05-15 14:38:26 +08:00
wangruidong
da0c017c4f fix: ldap定时任务未执行 2024-05-15 14:16:33 +08:00
fit2bot
5ffc0a9665 perf: add new dependencies (#13220)
Co-authored-by: feng <1304903146@qq.com>
2024-05-15 10:13:14 +08:00
fit2bot
10e9026ec7 perf: add gpt 4o (#13218)
Co-authored-by: feng <1304903146@qq.com>
2024-05-14 16:29:41 +08:00
Bai
7c4c0b5924 fix: Fixed ACLs Asset connect select attribute assets while both include labels not matched. 2024-05-14 16:16:00 +08:00
wangruidong
42c3008ec9 perf: 更新ldap相关翻译文件 2024-05-14 15:08:37 +08:00
吴小白
2f6d743cf0 perf: 优化 CI 构建测试 2024-05-14 14:17:02 +08:00
fit2bot
e8faaeb8fb fix: Accounts of ssh key type will no longer export fingerprints. (#13215)
Co-authored-by: feng <1304903146@qq.com>
2024-05-14 13:04:11 +08:00
jiangweidong
09f802b00d perf: cloud sync module adjustment (#13197)
* perf: cloud sync module adjustment

* perf: cloud sync module adjustment
2024-05-14 10:36:17 +08:00
wangruidong
a644b84bb1 perf: dashboard zh,ja,zh_hant i18n 2024-05-13 18:31:54 +08:00
吴小白
b6f48111e3 feat: 更新 Dockerfile 2024-05-13 18:25:06 +08:00
feng
0ea675f8d6 fix: windows gather account failed 2024-05-13 18:23:40 +08:00
wangruidong
3a6e4e7fb6 perf: file transfer boot step help tips i18n 2024-05-13 18:18:27 +08:00
wangruidong
e42a98ff95 perf: celery task log css optimize 2024-05-13 18:16:36 +08:00
ibuler
8fe511cec6 perf: remove *.mo 2024-05-13 17:35:00 +08:00
Bai
ffb3cd13cb perf: Delete locale dir 2024-05-13 17:26:38 +08:00
halo
77caa5536f fix: chrome应用加载多个插件不生效问题 2024-05-13 16:30:17 +08:00
Bai
b1abf8a339 perf: Merge local v4 2024-05-13 15:58:59 +08:00
ibuler
89d20c8a4d perf: 修改一些翻译 2024-05-13 15:28:11 +08:00
ibuler
d66f923c0c perf: 修改翻译 2024-05-13 10:40:08 +08:00
ibuler
d3c14428a1 perf: remove an or a 2024-05-13 10:35:21 +08:00
ibuler
c104f85b18 perf: 修改翻译 2024-05-13 10:29:26 +08:00
fit2bot
755d8124ac perf: account backup translate (#13198)
Co-authored-by: feng <1304903146@qq.com>
2024-05-11 19:48:15 +08:00
Bai
a029cc8ed5 perf: i18n Personal Settings -> All sub menu 2024-05-11 18:55:03 +08:00
ibuler
111dfa8c29 perf: 修改大小写 2024-05-11 16:03:40 +08:00
fit2bot
52c905832b fix: 账号密钥长度为8192时 刷新账号列表504 (#13196)
Co-authored-by: feng <1304903146@qq.com>
2024-05-11 14:45:29 +08:00
ibuler
5f892c3afe perf: change i18n 2024-05-11 14:41:58 +08:00
fit2bot
313202fe41 perf: 合并 migrations (#13187)
* perf: 修改 Migrations

* perf: 合并 migrations

* perf: remove unuse

* perf: change to file

---------

Co-authored-by: ibuler <ibuler@qq.com>
2024-05-11 11:22:01 +08:00
Bai
af1adc3baa perf: i18n Personal Settings -> All sub menu 2024-05-11 11:17:02 +08:00
ibuler
be214c84d1 merge: with dev 2024-05-10 18:10:18 +08:00
fit2bot
082614e7b0 perf: A wave of migration Japan, Taiwan China font (#13188)
Co-authored-by: feng <1304903146@qq.com>
2024-05-10 15:13:40 +08:00
Bai
94ee3169dc perf: While Asset amount (GLOBAL) > 5000 delay (20s) refresh user perm tree 2024-05-10 12:38:31 +08:00
wangruidong
83835747c5 perf: i18n 2024-05-10 10:06:44 +08:00
Bai
2a7b48c83d perf: i18n Personal Settings -> Profile 2024-05-09 15:26:38 +08:00
ibuler
a9068496d9 perf: 打算压缩 migratons 2024-05-09 11:01:01 +08:00
fit2bot
8bad88e798 perf: 优化账号相关翻译 (#13177)
Co-authored-by: feng <1304903146@qq.com>
2024-05-08 18:04:46 +08:00
fit2bot
92b6286feb fix: ldap更换OU后无法登录 (#13172)
* fix: ldap更换OU后无法登录

* perf: 翻译

---------

Co-authored-by: wangruidong <940853815@qq.com>
2024-05-08 14:23:20 +08:00
Bai
bce776bb63 fix: 修复 v2 升级到 v3 授权的手动登录系统用户显示空字符串的问题 2024-05-07 14:33:01 +08:00
吴小白
9f45eeeb1f fix: 优化构建缓存 2024-05-07 11:43:40 +08:00
wangruidong
dc39cbf037 fix: ldap定时任务未执行 2024-05-07 10:27:44 +08:00
吴小白
60110982f1 fix: 修正构建错误 2024-04-30 11:24:17 +08:00
ibuler
259204bfe2 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-04-30 10:42:31 +08:00
wangruidong
c55e9679db perf: dashboard i18n 2024-04-30 10:31:22 +08:00
ibuler
c05a3c315a Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-04-29 15:07:25 +08:00
ibuler
dbdf586f5b add i18n 2024-04-29 15:06:53 +08:00
Bai
b1bd4db3e9 perf: Update poetry.lock 2024-04-29 11:47:18 +08:00
fit2bot
7806a13db5 feat: 默认数据库使用 PostgreSQL (#13088)
Co-authored-by: 吴小白 <296015668@qq.com>
Co-authored-by: Bryan <jiangjie.bai@fit2cloud.com>
2024-04-29 11:46:16 +08:00
Bai
928f564109 merge: into dev from v4: poetry lock file updated 2024-04-29 11:20:37 +08:00
Bai
328f718fe8 merge: into dev from v4: i18n file 2024-04-29 11:16:09 +08:00
Bai
cb4402c610 merge: into dev from v4 2024-04-29 11:07:43 +08:00
feng626
fbc4cb9046 Revert "perf: remove ticket model" (#13145)
This reverts commit 94567b86f0.
2024-04-28 18:26:49 +08:00
feng
94567b86f0 perf: remove ticket model 2024-04-28 18:02:57 +08:00
Bai
38175d6b57 fix: Fixed csv file export for 0 chars is not appear 2024-04-28 17:56:45 +08:00
ibuler
8aa707427f pref: remove user source choice 2024-04-28 16:01:09 +08:00
wangruidong
7408ed0f03 perf: add XPACKModelFieldsMixin 2024-04-28 15:58:14 +08:00
wangruidong
5135186961 perf: 社区版去掉一些东西 2024-04-28 15:58:14 +08:00
wangruidong
5be399616b fix: 华为交换机执行某些命令报错 2024-04-28 14:17:38 +08:00
ibuler
7d64b8419f Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-04-28 14:04:55 +08:00
ibuler
fad9249810 perf: 再次修改菜单 2024-04-28 14:04:28 +08:00
wangruidong
46a23afbec perf: 创建、更新用户时MFA选项根据系统设置选项进行动态渲染 2024-04-26 11:35:56 +08:00
Bai
8c4add241d perf: Support django shell run orm output SQL 2024-04-26 10:39:49 +08:00
Bai
feee92daee fix: Fixed issue of v2 to v3 Account missing su_from 2024-04-25 19:13:34 +08:00
Bai
42054c7989 feat: Support asset tree node drag to another one 2024-04-24 18:05:51 +08:00
wangruidong
bb4fbc3a1c perf: index page typo 2024-04-24 18:05:03 +08:00
Aaron3S
9b20b67039 fix: 修复执行快捷命令时 local_connection 没有被正确设置 2024-04-23 19:07:22 +08:00
Bai
2acc84dc69 fix: Adhoc support mariadb with module of mysql 2024-04-23 18:57:08 +08:00
ibuler
d7916a62f0 perf: 修改翻译 2024-04-23 18:11:05 +08:00
吴小白
3383d0f314 perf: 镜像添加 nc 命令 2024-04-23 16:53:25 +08:00
Bai
c9858b5a84 fix: 修改配置 RECEPTOR_ENABLED=False 默认 2024-04-23 16:52:44 +08:00
Bai
25e21b185f fix: 修改配置 RECEPTOR_ENABLED 2024-04-23 15:03:04 +08:00
ibuler
da27e1b93c perf: 修改翻译 2024-04-23 14:16:21 +08:00
Aaron3S
720231f692 feat: 修改 receptor 容器通信地址 2024-04-23 13:12:18 +08:00
jiangweidong
95f29a584e perf: 优化会话过期500问题 2024-04-23 13:11:41 +08:00
Bai
50cbb75b96 perf: 优化 Web 资产详情时根据 autofill 类型返回对应的 spec_info 信息 2024-04-23 13:09:40 +08:00
Bai
67277dd622 fix: 修复仪表盘会话排序数量都是 1 的问题 2024-04-22 19:42:33 +08:00
Bryan
82e7f020ea Merge pull request #13094 from jumpserver/dev
v3.10.9 (dev to master)
2024-04-22 19:39:53 +08:00
Bai
d418647774 fix: 修复仪表盘会话排序数量都是 1 的问题 2024-04-22 19:37:45 +08:00
Bai
6b5d4a4810 fix: 修复仪表盘会话排序数量都是 1 的问题 2024-04-22 19:32:42 +08:00
Eric
2cc67634a4 perf: 发布机支持平台连接参数 2024-04-22 16:40:41 +08:00
ibuler
99b24cad00 perf: add open sans font 2024-04-22 15:08:28 +08:00
fit2bot
52922088a9 feat: 优化代码结构,receptor开关,修改为 tcp 通信 (#13078)
* feat: 优化代码结构,receptor开关,修改为 tcp 通信

* fix: 修改导包路径

* fix: 修复错别字

* fix: 修改导包路径

* perf: 优化代码

* fix: 修复任务不执行的问题

* perf: 优化配置项名称

* perf: 优化代码结构

* perf: 优化代码

---------

Co-authored-by: Aaron3S <chenyang@fit2cloud.com>
2024-04-22 13:51:52 +08:00
jiangweidong
ef7329a721 perf: 优化频繁发送短信,将后端的频繁发送警告提示到页面上来提醒用户 2024-04-22 13:20:51 +08:00
Bai
ad0bc82539 perf: 优化 HUAWEI 设备判断逻辑 2024-04-22 13:19:32 +08:00
wangruidong
1ecf8534f6 perf: 兼容自定义平台的华为交换机执行命令 2024-04-22 13:19:32 +08:00
feng
94286caec4 fix: 命令输出取消长度限制 2024-04-22 10:31:35 +08:00
wangruidong
d4c8425218 fix: 快捷命令账号选择未按账号数量排序 2024-04-22 10:31:02 +08:00
fit2bot
59f9a4f369 fix: 获取 k8s 树取消异常 返回空 优化错误日志 (#13077)
Co-authored-by: feng <1304903146@qq.com>
2024-04-19 17:41:41 +08:00
Bai
64125051df fix: Org is None not has id attribute 2024-04-19 17:15:30 +08:00
Bai
660572a0ea fix: merge_delay_run 偶尔会出现 (2006, MySQL server has gone away 的报错) 2024-04-19 17:15:30 +08:00
ibuler
c0273dc698 perf: 去掉 js 报错 2024-04-19 11:21:27 +08:00
Bai
2782d4b5f1 fix: 修复 Celery Execution 任务保存失败导致 View 事务回滚的问题(首次登录用户修改密码失败) 2024-04-18 21:21:09 +08:00
ibuler
9dbdd6ac60 perf: change i18n 2024-04-18 20:12:01 +08:00
Bryan
f20b9e01ab Merge pull request #13062 from jumpserver/dev
v3.10.8 dev to master
2024-04-18 18:01:20 +08:00
fit2bot
d4f9e30306 perf: translate (#13061)
Co-authored-by: feng <1304903146@qq.com>
2024-04-18 17:28:55 +08:00
Bryan
8cf8a3701b Merge pull request #13059 from jumpserver/dev
v3.10.8
2024-04-18 17:16:37 +08:00
Aaron3S
1b221d1cb6 fix: celery kwargs 参数解析问题 2024-04-18 17:06:09 +08:00
halo
fbf42ebbf9 perf: 更新客户端版本 2024-04-18 15:58:50 +08:00
Aaron3S
a0c4eae04c perf: 优化变量名, 防止和翻译方法冲突 2024-04-18 14:31:44 +08:00
Aaron3S
d1c293940a fix: 修复 celery task not found 的问题 2024-04-18 14:31:44 +08:00
Aaron3S
6f2d04a029 fix: 修复自动化任务重包含多个playbook runtime 目录被提前删除的问题 2024-04-18 14:10:34 +08:00
wangruidong
29dbc2e4d4 perf: 用户详情页-资产授权规则字段排序优化 2024-04-18 13:14:16 +08:00
wangruidong
e8d717d174 fix: 资产不存在指定用户的时候,没有用特权用户任务未执行 2024-04-17 20:17:24 +08:00
Aaron3S
138a3a2f46 fix: 修复 receptor_ctl 的并发安全问题 2024-04-17 18:58:20 +08:00
fit2bot
cade2cfa13 fix: 改密推送没有更新版本 (#13044)
Co-authored-by: feng <1304903146@qq.com>
2024-04-17 16:14:40 +08:00
wangruidong
ac988a76b4 fix: 重启服务禁用的定时任务会执行问题 2024-04-17 14:25:10 +08:00
ibuler
5a9815481a perf: 修改 token expire 逻辑 2024-04-17 14:23:56 +08:00
ibuler
f8953441e3 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-04-17 14:09:25 +08:00
ibuler
5b41eddacc perf: 修改翻译 2024-04-17 13:49:43 +08:00
feng
bfbddfdead fix: 【账号改密】任务列表-详情:获取任务记录tab报错 2024-04-17 11:27:18 +08:00
Aaron3S
3cf526fdf3 fix: 修复测试根节点连接性 task 找不到的问题 2024-04-16 19:27:56 +08:00
Aaron3S
f6a4ee54d0 fix: 补充遗漏的网关参数 2024-04-16 19:27:56 +08:00
wangruidong
5755d281d7 perf: ldap测试登录前端不需要先测试连接 2024-04-16 18:13:45 +08:00
Aaron3S
1569524583 fix: 修复调用 ssh_ping 模块测试走网关的资产连接性失败 2024-04-16 17:14:30 +08:00
fit2bot
7ba876eb0a fix: 登录复核 审批后 刷新页面工单没清除 (#13031)
Co-authored-by: feng <1304903146@qq.com>
2024-04-16 14:04:18 +08:00
wangruidong
a31ea77b3c fix: 会话详情中文件传输显示有误 2024-04-16 10:38:05 +08:00
Aaron3S
44445a9482 fix: 修复一些因使用 receptor runner 造成的 bug 2024-04-15 19:42:36 +08:00
Bai
b8449a6efa fix: Export csv file can run program for windows 2024-04-15 19:42:03 +08:00
fit2bot
ccf6b00084 perf: 迁移文件和翻译 (#13024)
Co-authored-by: feng <1304903146@qq.com>
2024-04-15 17:57:47 +08:00
fit2bot
4423f842e0 fix: 历史账号数量计算错误 (#13023)
Co-authored-by: feng <1304903146@qq.com>
2024-04-15 17:17:11 +08:00
ibuler
a432af1a6d perf: 修改翻译 2024-04-15 16:34:02 +08:00
fit2bot
7660e3228e fix: 【账号推送】创建账号推送失败 (#13021)
Co-authored-by: feng <1304903146@qq.com>
2024-04-15 14:48:58 +08:00
wangruidong
482f5613e4 fix: 会话详情中文件传输显示有误 2024-04-15 14:42:18 +08:00
Bai
3cfb46f798 fix: Update jms-storage version 0.0.57 2024-04-15 14:34:58 +08:00
吴小白
f987515b89 perf: 优化发布机日志输出 2024-04-15 12:04:26 +08:00
fit2bot
f0d1279a42 perf: 修改user session 权限判断 (#13019)
Co-authored-by: feng <1304903146@qq.com>
2024-04-15 11:26:22 +08:00
halo
140118c9c6 perf: 更新copyright年份 2024-04-15 10:33:45 +08:00
wangruidong
637b9b1b15 perf: 申请工单-指定账号信息优化 2024-04-12 13:26:23 +08:00
Aaron3S
969069dde0 feat: receptor 中添加环境变量 2024-04-12 13:24:54 +08:00
Jiangweidong
84a71c8b3a perf: 火山引擎翻译 2024-04-12 13:24:32 +08:00
fit2bot
f3bd727c32 perf: 改密失败发给收件人 (#13009)
Co-authored-by: feng <1304903146@qq.com>
2024-04-12 11:53:47 +08:00
Aaron3S
2ac87e4ad6 feat: 修改重复的删除目录的逻辑 2024-04-12 11:35:51 +08:00
fit2bot
3740a4ad6f fix: 开启仅一台设置登录 退出失败 (#13007)
Co-authored-by: feng <1304903146@qq.com>
2024-04-12 11:16:58 +08:00
fit2bot
3bc8db7c3d fix: 改密任务记录搜索失败 (#13006)
Co-authored-by: feng <1304903146@qq.com>
2024-04-12 11:02:47 +08:00
fit2bot
f3d19ad9f4 fix: 【Lark】绑定时,一些报错信息优化 (#13004)
Co-authored-by: feng <1304903146@qq.com>
2024-04-12 10:39:49 +08:00
Bai
d2396afdd5 fix: User my assets sorted by connectivity did not take effect 2024-04-12 10:39:34 +08:00
Eric
43f9c07838 perf: 优化任务日志输出 2024-04-11 22:27:44 +08:00
Aaron3S
6052306c04 feat: ansible receptor kill 进程 2024-04-11 22:26:01 +08:00
Aaron3S
6a12bc39e9 feat: ansible receptor 适配文件上传 2024-04-11 22:22:29 +08:00
Bai
3f67b40975 fix: Export excel file can running instructions(csv no need deal) 2024-04-11 20:37:17 +08:00
fit2bot
0adc854721 perf: 优化审计台命令记录代码 (#12998)
Co-authored-by: feng <1304903146@qq.com>
2024-04-11 18:32:00 +08:00
fit2bot
ab76745a9f perf: 优化审计台仪表盘命令记录总数统计数据库和所有es数据 (#12997)
Co-authored-by: feng <1304903146@qq.com>
2024-04-11 18:29:02 +08:00
Aaron3S
574639d5e1 feat: 支持 ansible receptor private 方式认证, 支持运行完成工作空间清理 2024-04-11 17:51:22 +08:00
fit2bot
fa5d9d3df4 fix: 二级审批通过,一级审批人员查看不到工单 (#12993)
Co-authored-by: feng <1304903146@qq.com>
2024-04-11 16:35:00 +08:00
Aaron3S
0c31925131 feat: 设置默认的 ansible 配置文件 2024-04-11 15:10:39 +08:00
wangruidong
94b5d8b9e9 perf: 处理停止任务异常情况 2024-04-11 14:25:40 +08:00
Bai
bffc9f4b1d fix: Fix session Duration label 2024-04-11 11:00:46 +08:00
wangruidong
6b5d18222e fix: 全局组织-组织角色用户数量不对 2024-04-10 18:20:05 +08:00
Aaron3S
2b05fd5276 fix: 修复 ansible receptor playbook 无法执行的问题 2024-04-10 18:18:32 +08:00
fit2bot
3e46d72ba3 fix: 修复lark登录 Backend错误问题 (#12981)
Co-authored-by: feng <1304903146@qq.com>
2024-04-10 17:07:48 +08:00
feng
6502adb772 perf: 切换zh hant 2024-04-10 14:39:58 +08:00
fit2bot
a8112c86e3 feat: 全面修改 ansible 执行方式为 receptor (#12975)
* feat: 修复 receptor kill job  的问题

* feat: 全面修改 ansible 执行方式为 receptor

---------

Co-authored-by: Aaron3S <chenyang@fit2cloud.com>
2024-04-10 11:35:38 +08:00
wangruidong
8911c9c649 fix: Luna引导下载版本更新 2024-04-09 20:10:30 +08:00
Bai
3b70b4cf9e feat: LDAP User Auth support cache user_dn 2024-04-09 20:09:50 +08:00
wangruidong
1e0ea3905e fix: 忘记密码短信验证码过期 2024-04-09 20:05:34 +08:00
ibuler
2afabd65f9 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-04-09 18:43:29 +08:00
ibuler
85cb80cbfe perf: remove gpt category 2024-04-09 18:43:06 +08:00
fit2bot
79f8480ae4 perf: core celery 不做报警 (#12970)
Co-authored-by: feng <1304903146@qq.com>
2024-04-09 17:07:48 +08:00
Bai
dec502e025 perf: Update user orgs roles 2024-04-09 16:52:11 +08:00
Aaron3S
c7b5cc7d89 feat: 暂时注释ansible runner write pid 逻辑 2024-04-09 16:46:56 +08:00
Aaron3S
bc76ce50e1 feat: 修改 receptor 启动参数 2024-04-09 15:59:14 +08:00
Bai
be90bf6b28 perf: Update user orgs roles 2024-04-09 15:43:27 +08:00
hzhfit2cloud
dfa68d1ca8 支持中文繁体 2024-04-09 15:18:36 +08:00
hzhfit2cloud
0237edf6c1 支持中文繁体 2024-04-09 15:18:36 +08:00
吴小白
6a87221c2a fix: 修正构建错误 2024-04-09 10:11:04 +08:00
ibuler
f0e87ef3f8 perf: rdp token 复用
perf: connection token
2024-04-08 19:03:47 +08:00
fit2bot
cd19a276c9 fix: 修复工单申请人过滤问题 (#12957)
Co-authored-by: feng <1304903146@qq.com>
2024-04-08 18:56:59 +08:00
jiangweidong
5ea4bba676 perf: 优化资产修改激活状态记录操作日志 2024-04-08 18:52:46 +08:00
吴小白
8500f186f6 perf: 优化镜像构建 2024-04-08 18:52:22 +08:00
Bryan
8c93d419fe Merge pull request #12956 from jumpserver/revert-12949-dev
Revert "feat: 支持中文繁体"
2024-04-08 18:05:45 +08:00
Bryan
2530827d07 Revert "feat: 支持中文繁体" 2024-04-08 18:04:38 +08:00
Bryan
8e54c446bc Merge pull request #12949 from elf168/dev
feat: 支持中文繁体
2024-04-08 18:02:31 +08:00
Bryan
3456e9ac5b Merge branch 'dev' into dev 2024-04-08 18:01:55 +08:00
fit2bot
689f858f97 feat: 支持 ansible 沙盒运行 (#12953)
* feat: 支持 ansible 沙盒运行

* feat: 修改 receptor sock 默认路径

* feat: 增加 adhoc 执行命令的 local connection 权限

---------

Co-authored-by: Aaron3S <chenyang@fit2cloud.com>
Co-authored-by: Bai <baijiangjie@gmail.com>
2024-04-08 17:54:34 +08:00
jiangweidong
93eebd7876 perf: 依赖包去掉多余的内容 2024-04-08 17:38:49 +08:00
jiangweidong
82cc21ef59 perf: 增加火山引擎依赖包volcengine-python-sdk 2024-04-08 17:38:49 +08:00
wangruidong
e61f9efbf2 perf: 内置平台置顶 2024-04-08 16:33:44 +08:00
ibuler
97f60a61e0 perf: 修改翻译 2024-04-08 14:32:14 +08:00
Bai
45bac09dc7 perf: ROOT Org show orgs-and-roles in user-detail page 2024-04-08 14:00:57 +08:00
Eddie
989a970a7c 簡轉繁 2024-04-07 10:57:48 +00:00
Eddie
0296df0480 簡轉繁 2024-04-07 10:31:04 +00:00
wangruidong
9776d35140 perf: 批量上传添加权限校验 2024-04-07 15:49:41 +08:00
fit2bot
0aeea414f5 fix: 支持 SSO 用户登录时校验 (#12923)
Co-authored-by: feng <1304903146@qq.com>
2024-04-07 14:57:38 +08:00
Bai
9817154234 perf: 优化所有View默认排序规则(name) 2024-04-03 19:10:34 +08:00
Bai
39ae14877b perf: 优化所有View默认排序规则(name) 2024-04-03 18:33:00 +08:00
Bai
9c238a9147 perf: 优化所有View默认排序规则(name) 2024-04-03 18:12:15 +08:00
fit2bot
42d7e983e4 perf: 翻译 (#12937)
Co-authored-by: feng <1304903146@qq.com>
2024-04-03 16:53:08 +08:00
fit2bot
611d0b71e8 fix: 修复用户下线失败问题 SESSION_EXPIRE_AT_BROWSER_CLOSE 可配置 (#12936)
Co-authored-by: feng <1304903146@qq.com>
2024-04-03 16:41:37 +08:00
Bai
d78d55091c fix: 修复过滤用户组织角色不生效的问题 2024-04-03 15:52:52 +08:00
ibuler
3b8aab8c25 perf: 修改 export 使用的 serializer 2024-04-02 19:15:48 +08:00
Eric
2f16bdc4be perf: 优化针对低版本 ssh 版本的任务 2024-04-02 19:01:21 +08:00
wangruidong
22d70eb416 fix: 华为交换机执行快捷命令报错 2024-04-02 18:48:40 +08:00
wangruidong
afa1ba4f6b fix: 统一成模板 2024-04-02 17:21:47 +08:00
ibuler
39d3e5477c perf: migrate label model with the id 2024-04-02 16:47:38 +08:00
Bryan
08ac8b0857 Update README.md 2024-04-02 15:27:28 +08:00
ibuler
255817f5c6 perf: 修改翻译 2024-04-02 14:27:18 +08:00
ibuler
19b196eb1f Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-04-01 19:28:26 +08:00
ibuler
40db6485dd perf: change i18n 2024-04-01 19:28:08 +08:00
Bryan
b23e99885e Update README.md 2024-04-01 18:47:29 +08:00
Bryan
22fbbb92da Update README.md 2024-04-01 18:41:34 +08:00
Bryan
99c94166bb Update README.md 2024-04-01 18:38:59 +08:00
Bryan
169254a1c7 Update README.md 2024-04-01 18:22:11 +08:00
Bryan
bda6037b2a Update README.md 2024-04-01 18:21:35 +08:00
Bryan
1cf0b15528 Update README.md 2024-04-01 18:08:47 +08:00
Bryan
ff3865d1a7 Update README.md 2024-04-01 18:01:56 +08:00
Bryan
10435788bc Update README.md 2024-04-01 17:37:11 +08:00
Bai
02750e56d9 perf: Update README.md 2024-04-01 17:09:08 +08:00
ibuler
a1d53cba44 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-03-29 19:01:01 +08:00
fit2bot
d499b94e04 fix: gpt 配置取消长度限制 (#12907)
Co-authored-by: feng <1304903146@qq.com>
2024-03-29 18:53:24 +08:00
Bai
b921ca8c9d perf: Update README.md 2024-03-29 18:46:11 +08:00
fit2bot
7a6468530f fix: 修复测试rdp资产可连接性时使用的python解释器路径不对问题 (#12902)
Co-authored-by: feng <1304903146@qq.com>
2024-03-29 16:09:42 +08:00
ibuler
29b38632e2 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-03-29 15:30:31 +08:00
ibuler
56193f833f perf: change some translation 2024-03-29 15:29:04 +08:00
fit2bot
02893c2a2b perf: 翻译 (#12899)
Co-authored-by: feng <1304903146@qq.com>
2024-03-29 15:18:54 +08:00
Eric
4470b68de9 perf: 优化代码,避免录像下载异常 2024-03-29 11:37:47 +08:00
wangruidong
d3d89b0853 perf: 去掉工单重新打开状态 2024-03-29 11:06:51 +08:00
wangruidong
681cecc52b perf: 优化所有资源列表的默认排序规则 2024-03-29 10:48:54 +08:00
Bryan
2c8b977001 Update README.md 2024-03-28 19:05:42 +08:00
Bryan
4827fcf243 Update README.md 2024-03-28 19:02:39 +08:00
fit2bot
3336a4526b fix: 解决beat无法在redis-ssl下运行报错的问题 (#12893)
Co-authored-by: jiangweidong <weidong.jiang@fit2cloud.com>
2024-03-28 18:44:52 +08:00
feng
bca0863952 fix: 【标签】标签绑定资源api需校验正确的uuid 2024-03-28 18:43:00 +08:00
Bryan
9140ed6969 Update README.md 2024-03-28 18:01:16 +08:00
Bryan
24e7597c67 Update README.md 2024-03-28 17:59:37 +08:00
Bryan
833dd654b2 Update README.md 2024-03-28 17:57:02 +08:00
Bryan
ae74154071 Update README.md 2024-03-28 17:52:37 +08:00
Bryan
fb1631c1c7 Update README.md 2024-03-28 17:49:53 +08:00
Bryan
1c6832b9b2 Update README.md 2024-03-28 17:11:55 +08:00
Bryan
77d06037bb Update README.md 2024-03-28 17:05:12 +08:00
Bai
136e62b97d perf: Update README.md 2024-03-28 17:02:52 +08:00
Bryan
24c36087dd Update README.md 2024-03-28 16:33:24 +08:00
Bryan
73f9d721fe Update README.md 2024-03-28 16:10:32 +08:00
Bryan
792f8b2d1f Update README.md 2024-03-28 16:08:05 +08:00
Bryan
6871d194a8 Update README.md 2024-03-28 16:07:22 +08:00
Bryan
12c26e4551 Update README.md 2024-03-28 15:56:55 +08:00
fit2bot
bf1a29fac2 fix: 修改content type 权限 (#12890)
Co-authored-by: feng <1304903146@qq.com>
2024-03-28 15:22:26 +08:00
wangruidong
47ceaf967c fix: 查看作业命令任务执行结果添加用户隔离 2024-03-28 14:42:08 +08:00
ibuler
3426f650fa Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-03-28 14:40:31 +08:00
feng
00c5b3c0a2 fix: 【资产登录】属性为标签时,规则不生效 2024-03-28 14:36:17 +08:00
ibuler
f224dc241e perf: 修改翻译 2024-03-28 14:31:27 +08:00
Bryan
f6effb3c40 Update README.md 2024-03-28 14:21:02 +08:00
Bryan
6bbdcc060d perf: Update README.md 2024-03-28 11:36:24 +08:00
Bryan
14411d8c86 Update README.md 2024-03-28 11:05:04 +08:00
Bryan
cca2bfee4e perf: Update README.md 2024-03-28 10:42:01 +08:00
Bryan
c6cc68601b perf: Update README.md 2024-03-28 10:40:48 +08:00
Bai
06f33e4bdc perf: Update README.md 2024-03-27 18:15:29 +08:00
ibuler
616b38158a Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-03-27 17:51:12 +08:00
ibuler
c22f88ae42 perf: 修改翻译 2024-03-27 17:50:44 +08:00
fit2bot
3aeadc2f03 fix: 修复收藏文件夹中的资产时不时莫名的丢失 (#12886)
Co-authored-by: feng <1304903146@qq.com>
2024-03-27 16:04:16 +08:00
wangruidong
f0cbd77310 perf: 优化资产、网域、网关的操作体验 2024-03-27 16:02:08 +08:00
Bai
3bf401f029 perf: Update README.md 2024-03-26 19:34:06 +08:00
Bai
0b8b74b7a4 perf: Update README.md 2024-03-26 18:48:10 +08:00
Bai
e1bd0ee3d7 perf: Update README.md 2024-03-26 18:30:30 +08:00
fit2bot
f11852c60d perf: lark logo (#12878)
Co-authored-by: feng <1304903146@qq.com>
2024-03-26 17:46:16 +08:00
Bai
4b0d95ed0c perf: Update README.md 2024-03-26 17:40:22 +08:00
feng
8b870678df perf: 翻译 2024-03-26 17:34:27 +08:00
feng
470a088a9f feat: 拆分 feishu lark 2024-03-26 17:10:25 +08:00
Bai
fedb146025 perf: Update README.md 2024-03-26 16:57:52 +08:00
Bai
695a5eb470 perf: Update README.md 2024-03-26 16:53:04 +08:00
jiangweidong
ccd4f3ada4 fix: tcpdump想捕捉所有ip时,空ip被解析成0.0.0.0,导致捕捉不到的问题 2024-03-22 17:31:03 +08:00
ibuler
ae7a562b85 fix: ansible playbook render and run in localhost 2024-03-22 17:06:19 +08:00
wangruidong
be6d8566da perf: 去掉enabled字段默认值 2024-03-22 16:02:25 +08:00
ibuler
f6e4d909ff Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-03-22 10:17:36 +08:00
ibuler
6c0299b05a perf: 优化语言更改 2024-03-21 19:13:00 +08:00
wangruidong
f264bf03ff feat: 支持开启、关闭定时任务执行 2024-03-21 18:23:41 +08:00
fit2bot
02c2ee8c54 perf: 登录界面文案优化 (#12849)
Co-authored-by: feng <1304903146@qq.com>
2024-03-21 16:21:44 +08:00
Eric
d71374ca8a perf: 优化代码 2024-03-21 16:08:34 +08:00
Eric
0589f7fe33 perf: 支持发布机卸载远程应用 2024-03-21 16:08:34 +08:00
fit2bot
a5e8792092 perf: 翻译 (#12847)
Co-authored-by: feng <1304903146@qq.com>
2024-03-21 11:32:23 +08:00
fit2bot
15acfe84b0 perf: 改密记录可查看密文 (#12821)
* perf: 改密记录可查看密文

* perf: 自动化任务错误处理

* feat: 改密记录可批量重试 新增更多过滤选项

* perf: 改密任务失败添加消息通知

---------

Co-authored-by: feng <1304903146@qq.com>
2024-03-21 11:05:04 +08:00
jiangweidong
08b483140c fix: 解决FTP审计文件无法清理的问题 2024-03-20 19:06:30 +08:00
Bai
cf1e048328 perf: 优化 Session 支持 duration 字段 2024-03-20 15:51:33 +08:00
Bai
fb02095568 perf: Remove settigns.LITE 2024-03-19 19:22:29 +08:00
Bai
d5675ce498 perf: update poetry.lock 2024-03-19 18:10:02 +08:00
ibuler
ccbb860de1 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-03-19 17:54:00 +08:00
ibuler
5e104a3dd2 perf: 修改翻译 2024-03-19 17:53:29 +08:00
Bai
51890c94cc perf: 对ce、ee依赖库进行分组 2024-03-19 16:35:15 +08:00
Bai
06259a2d63 perf: 对ce、ee依赖库进行分组 2024-03-19 16:31:45 +08:00
wangruidong
a6228f145d fix: 作业命令用户隔离执行 2024-03-19 11:25:46 +08:00
ibuler
b6ab3df038 perf: 优化 celery task log 权限控制 2024-03-18 19:00:04 +08:00
ibuler
e9f591b33b perf: 优化 ops task 2024-03-18 18:54:48 +08:00
wangruidong
90d4914280 perf: 删除job-execution/asset-detail接口 2024-03-18 18:54:27 +08:00
wangruidong
80a506e99f perf:LDAP报错信息不对 2024-03-18 15:56:57 +08:00
Eric
d8a891a7d7 perf: 支持发布机仅初始化配置 2024-03-18 15:52:42 +08:00
wangruidong
d71c41e384 perf: 提高短信发送任务优先级 2024-03-18 15:50:00 +08:00
fit2bot
bb27ff7f8a fix: 批量上传文件关闭作业中心配置后上传会报错 (#12814)
* fix: 批量上传文件关闭作业中心配置后上传会报错

* fix: format

---------

Co-authored-by: wangruidong <940853815@qq.com>
Co-authored-by: Bai <baijiangjie@gmail.com>
2024-03-18 15:49:13 +08:00
wangruidong
0671e56d65 fix: Another user can use this job id to spoof both the file name and
its contents
2024-03-18 14:22:17 +08:00
ibuler
d04ac09e82 perf: 修改 groups api 2024-03-15 19:18:49 +08:00
feng
73a4ce0943 perf: 优化user secret key 处理逻辑 2024-03-15 11:39:59 +08:00
fit2bot
902fac61e9 perf: playbook api 去掉多余的rbac_perms (#12813)
Co-authored-by: feng <1304903146@qq.com>
2024-03-14 14:27:31 +08:00
wangruidong
dcd7f9f7e6 perf: 支持终断批量快捷命令执行的任务 2024-03-14 14:20:47 +08:00
Bai
80035e7cb6 fix: 修复 Playbook 脚本文件问题 2024-03-14 10:26:30 +08:00
Eric
e2d14f5e4b perf: 支持 razor 的监控 2024-03-13 19:36:26 +08:00
ibuler
cae9f03892 perf: 修改 platform 翻译 2024-03-13 18:40:35 +08:00
刘瑞斌
a27cc22596 chore: edit readme_en 2024-03-13 15:47:04 +08:00
ibuler
72362274ce perf: 优化 console_orgs 的选择问题 2024-03-13 10:58:30 +08:00
feng
cfb1d306a3 perf: 优化user session 逻辑 2024-03-13 10:58:03 +08:00
ibuler
bffcd6107c perf: 修改翻译 2024-03-12 18:47:44 +08:00
wangruidong
e5cb99d682 perf: 登录页面排版优化 2024-03-12 17:05:03 +08:00
ibuler
056e0c816b perf: 修改翻译 2024-03-12 17:04:26 +08:00
fit2bot
cbd812ab5f feat: 自定义footer (#12795)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-03-12 14:36:20 +08:00
ibuler
ea67312877 perf: 修改翻译 2024-03-11 19:20:18 +08:00
Bai
d0117b5a91 perf: 优化邮箱校验逻辑 2024-03-11 18:41:50 +08:00
jiangweidong
afe3777895 perf: 减少一次邮箱的判断 2024-03-11 18:41:50 +08:00
jiangweidong
e45676edc4 perf: 优化获取邮箱后缀代码位置 2024-03-11 18:41:50 +08:00
jiangweidong
60e4b19d07 perf: 优化三方登录创建的用户邮箱会校验,非法邮箱会重置成默认格式 2024-03-11 18:41:50 +08:00
Bai
86d76c53d6 perf: 优化 MongoDB 数据库支持 authSource 认证数据库配置 2024-03-11 18:27:57 +08:00
fit2bot
b50f1a662d fix: 优化手动输入的账号username遵循登录资产的ACL控制 (#12774)
Co-authored-by: feng <1304903146@qq.com>
2024-03-11 15:10:51 +08:00
fit2bot
b3e4c10bc2 perf: 用户个人设置操作记录翻译 (#12788)
Co-authored-by: feng <1304903146@qq.com>
2024-03-11 15:10:15 +08:00
ibuler
327cdc8604 perf: 修改翻译 2024-03-11 14:33:14 +08:00
Bai
ba11e646d6 fix: 修复 redis lock 导致 celery 异步任务卡住不执行的问题 2024-03-11 14:12:18 +08:00
wangruidong
6de524c797 perf: 不满足自动登录勾选条件时从禁用修改为隐藏 2024-03-08 18:35:18 +08:00
Bai
2e067a7950 perf: 优化升级 django-celery-beat==2.6.0; 删除之前修复的 celery-beat 的代码 2024-03-08 17:47:07 +08:00
fit2bot
a3658136e2 feat: 支持配置资产连接默认打开方式 (#12781)
Co-authored-by: feng <1304903146@qq.com>
2024-03-08 10:47:18 +08:00
Bai
4108415894 perf: 优化 issue 提交模版 2024-03-08 10:33:04 +08:00
Bai
ae2fdff9a7 perf: 优化 issue 提交模版 2024-03-07 18:58:28 +08:00
ibuler
6f37cc4d01 merge: with remote 2024-03-07 18:36:03 +08:00
ibuler
003dd49ed6 perf: 修改翻译 2024-03-07 18:33:13 +08:00
Bai
46d57f02e7 perf: i18n settings-systemtask done. 2024-03-07 17:29:03 +08:00
Bai
30915a93e5 perf: i18n settings-tools done. 2024-03-07 16:15:09 +08:00
Bryan
b9422c096e fix: 修复连接 Token 时报错的问题((1139, "Got error empty (sub)expression from regexp")) (#12768) 2024-03-07 12:37:33 +08:00
fit2bot
b3e73605b0 perf: 创建网域时资产不用必选 (#12766)
Co-authored-by: feng <1304903146@qq.com>
2024-03-07 11:20:40 +08:00
Bai
c64480dc33 perf: i18n settings-Interface not done. 2024-03-06 17:49:42 +08:00
ibuler
4a9b1aff96 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-03-06 17:08:31 +08:00
ibuler
542e94ec9c perf: 修改翻译 2024-03-06 17:08:24 +08:00
fit2bot
9341558f61 perf: translate (#12764)
Co-authored-by: feng <1304903146@qq.com>
2024-03-06 16:51:07 +08:00
fit2bot
6c89349194 perf: 优化会话 命令记录 分片删除 (#12763)
Co-authored-by: feng <1304903146@qq.com>
2024-03-06 15:22:55 +08:00
jiangweidong
670eac49b6 perf: 优化oauth2登录未激活用户时,会重复跳转登录问题 2024-03-06 15:03:58 +08:00
feng
a7a099f290 perf: 支持配置文件配置限制的最大数量 2024-03-06 14:53:48 +08:00
feng
5157514c62 perf: 优化会话清理任务使用分片删除过期的会话和命令 2024-03-06 14:50:19 +08:00
jiangweidong
533d2ab98a perf: 优化自定义短信测试总是成功的问题 2024-03-06 14:32:58 +08:00
ibuler
6ea13b2c0d perf: 修改翻译 2024-03-05 19:01:44 +08:00
wangruidong
40730b741d fix: 个别页面搜索不生效的问题 2024-03-05 11:21:20 +08:00
ibuler
e57512f4fe perf: 添加配置支持 Lite 2024-03-04 19:18:26 +08:00
ibuler
348f67f4a4 Merge branch 'v4' of github.com:jumpserver/jumpserver into v4 2024-03-04 15:46:18 +08:00
ibuler
83bdf07600 perf: 修改翻译 2024-03-04 15:42:14 +08:00
fit2bot
dfe4eddbbc perf: translate (#12746)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-03-04 14:44:19 +08:00
ibuler
1caed59f76 merge: with remote 2024-03-04 14:03:05 +08:00
Bai
6db4e88a2c perf: 更新 poetry.lock 文件 2024-03-04 11:32:04 +08:00
halo
786cb23f98 perf: 优化ansible_winrm执行超时时间 2024-03-01 17:02:48 +08:00
fit2bot
133daeb664 perf: translate (#12739)
Co-authored-by: feng <1304903146@qq.com>
2024-03-01 15:42:21 +08:00
fit2bot
518ae3fa09 perf: 自动化资产探活支持Telnet方式 (#12728)
Co-authored-by: jiangweidong <weidong.jiang@fit2cloud.com>
2024-03-01 15:05:34 +08:00
ibuler
18707d365b perf: 优化标签搜索资产使用的关系 2024-03-01 15:05:01 +08:00
wangruidong
a4a8d1ecf0 perf: modify menu translate 2024-03-01 13:53:29 +08:00
ibuler
88a08a74f7 perf: 修改翻译 2024-02-29 14:57:38 +08:00
feng
c9e12a3027 perf: Modify some translations 2024-02-28 18:23:10 +08:00
fit2bot
82aa4a65ab perf: account translate (#12723)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-02-28 17:32:29 +08:00
ibuler
d46237f1bf merge: with remote 2024-02-28 16:32:46 +08:00
ibuler
1744f94910 perf: 修改翻译 2024-02-28 16:27:41 +08:00
Bai
e308812429 perf: i18n settings-Security done. 2024-02-27 19:20:48 +08:00
fit2bot
2328ef0b0c perf: account translate (#12719)
Co-authored-by: feng <1304903146@qq.com>
2024-02-27 19:17:40 +08:00
Bai
000c5770f2 perf: i18n settings-RemoteApp done. 2024-02-27 17:13:59 +08:00
Bai
9e1a3598ab perf: i18n settings-Components done. 2024-02-27 16:43:44 +08:00
Bai
7268f60343 perf: i18n settings-Storage done. 2024-02-27 14:59:22 +08:00
Bai
c8b274031f perf: i18n settings-Auth done. 2024-02-27 11:25:42 +08:00
Bai
10394dbb1c perf: i18n settings-Auth done. 2024-02-26 16:53:40 +08:00
Bai
859bb91fc7 perf: i18n settings-Features done. 2024-02-26 15:47:05 +08:00
fit2bot
0fd0d33704 perf: i18n settings-notifications done. (#12702)
Co-authored-by: Bai <baijiangjie@gmail.com>
Co-authored-by: Bryan <jiangjie.bai@fit2cloud.com>
2024-02-23 18:09:18 +08:00
fit2bot
ad0f489834 perf: translate (#12701)
Co-authored-by: feng <1304903146@qq.com>
2024-02-23 17:52:16 +08:00
fit2bot
b1fa870de7 perf: 工作台相关翻译 (#12700)
Co-authored-by: feng <1304903146@qq.com>
Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com>
2024-02-23 17:22:47 +08:00
Bai
7c5e2ae8ea perf: i18n settings-org done. 2024-02-23 15:17:17 +08:00
Bai
c0e4065a45 perf: i18n settings-basic done. 2024-02-23 14:31:09 +08:00
fit2bot
35448eea9f perf: 翻译 (#12690)
Co-authored-by: feng <1304903146@qq.com>
2024-02-22 17:46:12 +08:00
wangruidong
430f45a3ec perf: permissions i18n modify 2024-02-22 17:36:45 +08:00
Bai
71b6fd5326 perf: 修改翻译 2024-02-22 17:29:46 +08:00
wangruidong
251db733b2 perf: i18n modify 2024-02-22 10:30:15 +08:00
ibuler
d799725b8a perf: 修改翻译 2024-02-20 19:01:32 +08:00
ibuler
9d80aed468 perf: 修改一些翻译 2024-02-06 15:51:39 +08:00
老广
96f92f0908 Merge pull request #12643 from jumpserver/pr@v4@perf_i18n
perf: 优化翻译
2024-02-05 14:18:48 +08:00
ibuler
314e4301f3 perf: 修改翻译 2024-02-05 14:13:07 +08:00
ibuler
b284bb60f5 merge: with dev 2024-02-05 09:49:43 +08:00
ibuler
f99396ec50 perf: 修改翻译 2024-02-04 19:31:51 +08:00
ibuler
886cf6ed1f perf: 暂存 2024-02-04 16:46:33 +08:00
ibuler
74dd6e97a2 perf: 优化翻译 2024-02-04 10:23:54 +08:00
fit2bot
46fde2f1aa perf: 整合翻译 (#12630)
* stash

* stash

* perf: 整合翻译

* perf: 整理了一遍

---------

Co-authored-by: ibuler <ibuler@qq.com>
2024-02-01 16:02:31 +08:00
fit2bot
e2a3c360ea perf: 修改一次性翻译长度 (#12557)
Co-authored-by: feng <1304903146@qq.com>
2024-01-17 11:38:58 +08:00
fit2bot
9968617758 perf: 修改优化结构 (#12554)
* perf: 修改优化结构

* perf: 修改结构

---------

Co-authored-by: ibuler <ibuler@qq.com>
2024-01-17 11:08:39 +08:00
feng
1cec27ed70 perf: 添加进度条 2024-01-17 10:36:45 +08:00
feng
f0dfff0625 feat: gpt translate 2024-01-16 16:19:37 +08:00
fit2bot
fdaec3c959 perf: Modify i18n for settings module. (#12543)
Co-authored-by: Bai <baijiangjie@gmail.com>
2024-01-15 04:41:50 -07:00
ibuler
fcb4c6a972 perf: Add sort json script 2024-01-15 17:12:13 +08:00
ibuler
513974bbed perf: remove some category 2024-01-15 16:38:16 +08:00
ibuler
00d6effd69 pref: stash 2024-01-11 18:33:52 +08:00
ibuler
c06c68d5da perf: 统一翻译 2024-01-11 14:40:44 +08:00
992 changed files with 51332 additions and 33902 deletions

View File

@@ -1,11 +0,0 @@
---
name: 需求建议
about: 提出针对本项目的想法和建议
title: "[Feature] "
labels: 类型:需求
assignees:
- ibuler
- baijiangjie
---
**请描述您的需求或者改进建议.**

72
.github/ISSUE_TEMPLATE/1_bug_report.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
name: '🐛 Bug Report'
description: 'Report an Bug'
title: '[Bug] '
labels: ['🐛 Bug']
assignees:
- baijiangjie
body:
- type: input
attributes:
label: 'Product Version'
description: The versions prior to v2.28 (inclusive) are no longer supported.
validations:
required: true
- type: checkboxes
attributes:
label: 'Product Edition'
options:
- label: 'Community Edition'
- label: 'Enterprise Edition'
- label: 'Enterprise Trial Edition'
validations:
required: true
- type: checkboxes
attributes:
label: 'Installation Method'
options:
- label: 'Online Installation (One-click command installation)'
- label: 'Offline Package Installation'
- label: 'All-in-One'
- label: '1Panel'
- label: 'Kubernetes'
- label: 'Source Code'
- type: textarea
attributes:
label: 'Environment Information'
description: Please provide a clear and concise description outlining your environment information.
validations:
required: true
- type: textarea
attributes:
label: '🐛 Bug Description'
description:
Please provide a clear and concise description of the defect. If the issue is complex, please provide detailed explanations. <br/>
Unclear descriptions will not be processed. Please ensure you provide enough detail and information to support replicating and fixing the defect.
validations:
required: true
- type: textarea
attributes:
label: 'Recurrence Steps'
description: Please provide a clear and concise description outlining how to reproduce the issue.
validations:
required: true
- type: textarea
attributes:
label: 'Expected Behavior'
description: Please provide a clear and concise description of what you expect to happen.
- type: textarea
attributes:
label: 'Additional Information'
description: Please add any additional background information about the issue here.
- type: textarea
attributes:
label: 'Attempted Solutions'
description: If you have already attempted to solve the issue, please list the solutions you have tried here.

View File

@@ -0,0 +1,72 @@
name: '🐛 反馈缺陷'
description: '反馈一个缺陷'
title: '[Bug] '
labels: ['🐛 Bug']
assignees:
- baijiangjie
body:
- type: input
attributes:
label: '产品版本'
description: 不再支持 v2.28(含)之前的版本。
validations:
required: true
- type: checkboxes
attributes:
label: '版本类型'
options:
- label: '社区版'
- label: '企业版'
- label: '企业试用版'
validations:
required: true
- type: checkboxes
attributes:
label: '安装方式'
options:
- label: '在线安装 (一键命令安装)'
- label: '离线包安装'
- label: 'All-in-One'
- label: '1Panel'
- label: 'Kubernetes'
- label: '源码安装'
- type: textarea
attributes:
label: '环境信息'
description: 请提供一个清晰且简洁的描述,说明你的环境信息。
validations:
required: true
- type: textarea
attributes:
label: '🐛 缺陷描述'
description: |
请提供一个清晰且简洁的缺陷描述,如果问题比较复杂,也请详细说明。<br/>
针对不清晰的描述信息将不予处理。请确保提供足够的细节和信息,以支持对缺陷进行复现和修复。
validations:
required: true
- type: textarea
attributes:
label: '复现步骤'
description: 请提供一个清晰且简洁的描述,说明如何复现问题。
validations:
required: true
- type: textarea
attributes:
label: '期望结果'
description: 请提供一个清晰且简洁的描述,说明你期望发生什么。
- type: textarea
attributes:
label: '补充信息'
description: 在这里添加关于问题的任何其他背景信息。
- type: textarea
attributes:
label: '尝试过的解决方案'
description: 如果你已经尝试解决问题,请在此列出你尝试过的解决方案。

View File

@@ -0,0 +1,56 @@
name: '⭐️ Feature Request'
description: 'Suggest an idea'
title: '[Feature] '
labels: ['⭐️ Feature Request']
assignees:
- baijiangjie
- ibuler
body:
- type: input
attributes:
label: 'Product Version'
description: The versions prior to v2.28 (inclusive) are no longer supported.
validations:
required: true
- type: checkboxes
attributes:
label: 'Product Edition'
options:
- label: 'Community Edition'
- label: 'Enterprise Edition'
- label: 'Enterprise Trial Edition'
validations:
required: true
- type: checkboxes
attributes:
label: 'Installation Method'
options:
- label: 'Online Installation (One-click command installation)'
- label: 'Offline Package Installation'
- label: 'All-in-One'
- label: '1Panel'
- label: 'Kubernetes'
- label: 'Source Code'
- type: textarea
attributes:
label: '⭐️ Feature Description'
description: |
Please add a clear and concise description of the problem you aim to solve with this feature request.<br/>
Unclear descriptions will not be processed.
validations:
required: true
- type: textarea
attributes:
label: 'Proposed Solution'
description: Please provide a clear and concise description of the solution you desire.
validations:
required: true
- type: textarea
attributes:
label: 'Additional Information'
description: Please add any additional background information about the issue here.

View File

@@ -0,0 +1,56 @@
name: '⭐️ 功能需求'
description: '提出需求或建议'
title: '[Feature] '
labels: ['⭐️ Feature Request']
assignees:
- baijiangjie
- ibuler
body:
- type: input
attributes:
label: '产品版本'
description: 不再支持 v2.28(含)之前的版本。
validations:
required: true
- type: checkboxes
attributes:
label: '版本类型'
options:
- label: '社区版'
- label: '企业版'
- label: '企业试用版'
validations:
required: true
- type: checkboxes
attributes:
label: '安装方式'
options:
- label: '在线安装 (一键命令安装)'
- label: '离线包安装'
- label: 'All-in-One'
- label: '1Panel'
- label: 'Kubernetes'
- label: '源码安装'
- type: textarea
attributes:
label: '⭐️ 需求描述'
description: |
请添加一个清晰且简洁的问题描述,阐述你希望通过这个功能需求解决的问题。<br/>
针对不清晰的描述信息将不予处理。
validations:
required: true
- type: textarea
attributes:
label: '解决方案'
description: 请清晰且简洁地描述你想要的解决方案。
validations:
required: true
- type: textarea
attributes:
label: '补充信息'
description: 在这里添加关于问题的任何其他背景信息。

60
.github/ISSUE_TEMPLATE/3_question.yml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: '🤔 Question'
description: 'Pose a question'
title: '[Question] '
labels: ['🤔 Question']
assignees:
- baijiangjie
body:
- type: input
attributes:
label: 'Product Version'
description: The versions prior to v2.28 (inclusive) are no longer supported.
validations:
required: true
- type: checkboxes
attributes:
label: 'Product Edition'
options:
- label: 'Community Edition'
- label: 'Enterprise Edition'
- label: 'Enterprise Trial Edition'
validations:
required: true
- type: checkboxes
attributes:
label: 'Installation Method'
options:
- label: 'Online Installation (One-click command installation)'
- label: 'Offline Package Installation'
- label: 'All-in-One'
- label: '1Panel'
- label: 'Kubernetes'
- label: 'Source Code'
- type: textarea
attributes:
label: 'Environment Information'
description: Please provide a clear and concise description outlining your environment information.
validations:
required: true
- type: textarea
attributes:
label: '🤔 Question Description'
description: |
Please provide a clear and concise description of the defect. If the issue is complex, please provide detailed explanations. <br/>
Unclear descriptions will not be processed.
validations:
required: true
- type: textarea
attributes:
label: 'Expected Behavior'
description: Please provide a clear and concise description of what you expect to happen.
- type: textarea
attributes:
label: 'Additional Information'
description: Please add any additional background information about the issue here.

View File

@@ -0,0 +1,61 @@
name: '🤔 问题咨询'
description: '提出一个问题'
title: '[Question] '
labels: ['🤔 Question']
assignees:
- baijiangjie
body:
- type: input
attributes:
label: '产品版本'
description: 不再支持 v2.28(含)之前的版本。
validations:
required: true
- type: checkboxes
attributes:
label: '版本类型'
options:
- label: '社区版'
- label: '企业版'
- label: '企业试用版'
validations:
required: true
- type: checkboxes
attributes:
label: '安装方式'
options:
- label: '在线安装 (一键命令安装)'
- label: '离线包安装'
- label: 'All-in-One'
- label: '1Panel'
- label: 'Kubernetes'
- label: '源码安装'
- type: textarea
attributes:
label: '环境信息'
description: 请在此详细描述你的环境信息,如操作系统、浏览器和部署架构等。
validations:
required: true
- type: textarea
attributes:
label: '🤔 问题描述'
description: |
请提供一个清晰且简洁的问题描述,如果问题比较复杂,也请详细说明。<br/>
针对不清晰的描述信息将不予处理。
validations:
required: true
- type: textarea
attributes:
label: '期望结果'
description: 请提供一个清晰且简洁的描述,说明你期望发生什么。
- type: textarea
attributes:
label: '补充信息'
description: 在这里添加关于问题的任何其他背景信息。

View File

@@ -1,22 +0,0 @@
---
name: Bug 提交
about: 提交产品缺陷帮助我们更好的改进
title: "[Bug] "
labels: 类型:Bug
assignees:
- baijiangjie
---
**JumpServer 版本( v2.28 之前的版本不再支持 )**
**浏览器版本**
**Bug 描述**
**Bug 重现步骤(有截图更好)**
1.
2.
3.

View File

@@ -1,10 +0,0 @@
---
name: 问题咨询
about: 提出针对本项目安装部署、使用及其他方面的相关问题
title: "[Question] "
labels: 类型:提问
assignees:
- baijiangjie
---
**请描述您的问题.**

View File

@@ -12,7 +12,9 @@ jobs:
uses: actions-cool/issues-helper@v2
with:
actions: 'close-issues'
labels: '状态:待反馈'
labels: '⏳ Pending feedback'
inactive-day: 30
body: |
You haven't provided feedback for over 30 days.
We will close this issue. If you have any further needs, you can reopen it or submit a new issue.
您超过 30 天未反馈信息,我们将关闭该 issue如有需求您可以重新打开或者提交新的 issue。

View File

@@ -13,4 +13,4 @@ jobs:
if: ${{ !github.event.issue.pull_request }}
with:
actions: 'remove-labels'
labels: '状态:待处理,状态:待反馈'
labels: '🔔 Pending processing,⏳ Pending feedback'

View File

@@ -13,13 +13,13 @@ jobs:
uses: actions-cool/issues-helper@v2
with:
actions: 'add-labels'
labels: '状态:待处理'
labels: '🔔 Pending processing'
- name: Remove require reply label
uses: actions-cool/issues-helper@v2
with:
actions: 'remove-labels'
labels: '状态:待反馈'
labels: '⏳ Pending feedback'
add-label-if-is-member:
runs-on: ubuntu-latest
@@ -55,11 +55,11 @@ jobs:
uses: actions-cool/issues-helper@v2
with:
actions: 'add-labels'
labels: '状态:待反馈'
labels: '⏳ Pending feedback'
- name: Remove require handle label
if: contains(steps.member_names.outputs.data, github.event.comment.user.login)
uses: actions-cool/issues-helper@v2
with:
actions: 'remove-labels'
labels: '状态:待处理'
labels: '🔔 Pending processing'

View File

@@ -13,4 +13,4 @@ jobs:
if: ${{ !github.event.issue.pull_request }}
with:
actions: 'add-labels'
labels: '状态:待处理'
labels: '🔔 Pending processing'

View File

@@ -1,36 +1,63 @@
name: "Run Build Test"
on:
push:
branches:
- pr@*
- repr@*
paths:
- 'Dockerfile'
- 'Dockerfile*'
- 'Dockerfile-*'
- 'pyproject.toml'
- 'poetry.lock'
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
component: [core]
version: [v4]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/setup-qemu-action@v2
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare Build
run: |
sed -i 's@^FROM registry.fit2cloud.com/jumpserver@FROM ghcr.io/jumpserver@g' Dockerfile-ee
- uses: docker/setup-buildx-action@v2
- uses: docker/build-push-action@v3
- name: Build CE Image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: jumpserver/core-ce:test
file: Dockerfile-ce
push: true
file: Dockerfile
tags: ghcr.io/jumpserver/${{ matrix.component }}:${{ matrix.version }}-ce
platforms: linux/amd64
build-args: |
VERSION=${{ matrix.version }}
APT_MIRROR=http://deb.debian.org
PIP_MIRROR=https://pypi.org/simple
PIP_JMS_MIRROR=https://pypi.org/simple
outputs: type=image,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true
cache-from: type=gha
cache-to: type=gha,mode=max
- uses: LouisBrunner/checks-action@v1.5.0
if: always()
- name: Build EE Image
uses: docker/build-push-action@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
name: Check Build
conclusion: ${{ job.status }}
context: .
push: false
file: Dockerfile-ee
tags: ghcr.io/jumpserver/${{ matrix.component }}:${{ matrix.version }}
platforms: linux/amd64
build-args: |
VERSION=${{ matrix.version }}
APT_MIRROR=http://deb.debian.org
PIP_MIRROR=https://pypi.org/simple
outputs: type=image,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true
cache-from: type=gha
cache-to: type=gha,mode=max

View File

@@ -10,3 +10,4 @@ jobs:
- uses: jumpserver/action-generic-handler@master
env:
GITHUB_TOKEN: ${{ secrets.PRIVATE_TOKEN }}
I18N_TOKEN: ${{ secrets.I18N_TOKEN }}

2
.gitignore vendored
View File

@@ -43,3 +43,5 @@ releashe
data/*
test.py
.history/
.test/
*.mo

View File

@@ -1,5 +1,10 @@
# Contributing
As a contributor, you should agree that:
- The producer can adjust the open-source agreement to be more strict or relaxed as deemed necessary.
- Your contributed code may be used for commercial purposes, including but not limited to its cloud business operations.
## Create pull request
PR are always welcome, even if they only contain small fixes like typos or a few lines of code. If there will be a significant effort, please document it as an issue and get a discussion going before starting to work on it.

139
Dockerfile Normal file
View File

@@ -0,0 +1,139 @@
FROM debian:bullseye-slim AS stage-1
ARG TARGETARCH
ARG DEPENDENCIES=" \
ca-certificates \
wget"
ARG APT_MIRROR=http://mirrors.ustc.edu.cn
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
set -ex \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
&& echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \
&& sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends ${DEPENDENCIES} \
&& echo "no" | dpkg-reconfigure dash
WORKDIR /opt
ARG CHECK_VERSION=v1.0.2
RUN set -ex \
&& wget https://github.com/jumpserver-dev/healthcheck/releases/download/${CHECK_VERSION}/check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz \
&& tar -xf check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz \
&& mv check /usr/local/bin/ \
&& chown root:root /usr/local/bin/check \
&& chmod 755 /usr/local/bin/check \
&& rm -f check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz
ARG VERSION
WORKDIR /opt/jumpserver
ADD . .
RUN echo > /opt/jumpserver/config.yml \
&& \
if [ -n "${VERSION}" ]; then \
sed -i "s@VERSION = .*@VERSION = '${VERSION}'@g" apps/jumpserver/const.py; \
fi
FROM python:3.11-slim-bullseye AS stage-2
ARG TARGETARCH
ARG BUILD_DEPENDENCIES=" \
g++ \
make \
pkg-config"
ARG DEPENDENCIES=" \
default-libmysqlclient-dev \
freetds-dev \
gettext \
libkrb5-dev \
libldap2-dev \
libsasl2-dev"
ARG APT_MIRROR=http://mirrors.ustc.edu.cn
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
set -ex \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
&& echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \
&& sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \
&& apt-get -y install --no-install-recommends ${DEPENDENCIES} \
&& echo "no" | dpkg-reconfigure dash
WORKDIR /opt/jumpserver
ARG PIP_MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple
RUN --mount=type=cache,target=/root/.cache,sharing=locked,id=core \
--mount=type=bind,source=poetry.lock,target=poetry.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
set -ex \
&& python3 -m venv /opt/py3 \
&& pip install poetry -i ${PIP_MIRROR} \
&& poetry config virtualenvs.create false \
&& . /opt/py3/bin/activate \
&& poetry install --only main
COPY --from=stage-1 /opt/jumpserver /opt/jumpserver
RUN set -ex \
&& export SECRET_KEY=$(head -c100 < /dev/urandom | base64 | tr -dc A-Za-z0-9 | head -c 48) \
&& . /opt/py3/bin/activate \
&& cd apps \
&& python manage.py compilemessages
FROM python:3.11-slim-bullseye
ARG TARGETARCH
ENV LANG=en_US.UTF-8 \
PATH=/opt/py3/bin:$PATH
ARG DEPENDENCIES=" \
libldap2-dev \
libx11-dev"
ARG TOOLS=" \
ca-certificates \
default-libmysqlclient-dev \
openssh-client \
sshpass \
bubblewrap"
ARG APT_MIRROR=http://mirrors.ustc.edu.cn
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
set -ex \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
&& echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \
&& sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& apt-get update \
&& apt-get -y install --no-install-recommends ${DEPENDENCIES} \
&& apt-get -y install --no-install-recommends ${TOOLS} \
&& mkdir -p /root/.ssh/ \
&& echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null\n\tCiphers +aes128-cbc\n\tKexAlgorithms +diffie-hellman-group1-sha1\n\tHostKeyAlgorithms +ssh-rsa" > /root/.ssh/config \
&& echo "no" | dpkg-reconfigure dash \
&& sed -i "s@# export @export @g" ~/.bashrc \
&& sed -i "s@# alias @alias @g" ~/.bashrc
COPY --from=stage-2 /opt /opt
COPY --from=stage-1 /usr/local/bin /usr/local/bin
COPY --from=stage-1 /opt/jumpserver/apps/libs/ansible/ansible.cfg /etc/ansible/
WORKDIR /opt/jumpserver
ARG VERSION
ENV VERSION=$VERSION
VOLUME /opt/jumpserver/data
ENTRYPOINT ["./entrypoint.sh"]
EXPOSE 8080
STOPSIGNAL SIGQUIT
CMD ["start", "all"]

View File

@@ -1,126 +0,0 @@
FROM python:3.11-slim-bullseye as stage-1
ARG TARGETARCH
ARG VERSION
ENV VERSION=$VERSION
WORKDIR /opt/jumpserver
ADD . .
RUN echo > /opt/jumpserver/config.yml \
&& cd utils && bash -ixeu build.sh
FROM python:3.11-slim-bullseye as stage-2
ARG TARGETARCH
ARG BUILD_DEPENDENCIES=" \
g++ \
make \
pkg-config"
ARG DEPENDENCIES=" \
freetds-dev \
libffi-dev \
libjpeg-dev \
libkrb5-dev \
libldap2-dev \
libpq-dev \
libsasl2-dev \
libssl-dev \
libxml2-dev \
libxmlsec1-dev \
libxmlsec1-openssl \
freerdp2-dev \
libaio-dev"
ARG TOOLS=" \
ca-certificates \
curl \
default-libmysqlclient-dev \
default-mysql-client \
git \
git-lfs \
unzip \
xz-utils \
wget"
ARG APT_MIRROR=http://mirrors.ustc.edu.cn
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core-apt \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=core-apt \
sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& apt-get update \
&& apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \
&& apt-get -y install --no-install-recommends ${DEPENDENCIES} \
&& apt-get -y install --no-install-recommends ${TOOLS} \
&& echo "no" | dpkg-reconfigure dash
WORKDIR /opt/jumpserver
ARG PIP_MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple
RUN --mount=type=cache,target=/root/.cache \
--mount=type=bind,source=poetry.lock,target=/opt/jumpserver/poetry.lock \
--mount=type=bind,source=pyproject.toml,target=/opt/jumpserver/pyproject.toml \
set -ex \
&& python3 -m venv /opt/py3 \
&& pip install poetry -i ${PIP_MIRROR} \
&& poetry config virtualenvs.create false \
&& . /opt/py3/bin/activate \
&& poetry install
FROM python:3.11-slim-bullseye
ARG TARGETARCH
ENV LANG=zh_CN.UTF-8 \
PATH=/opt/py3/bin:$PATH
ARG DEPENDENCIES=" \
libjpeg-dev \
libpq-dev \
libx11-dev \
freerdp2-dev \
libxmlsec1-openssl"
ARG TOOLS=" \
ca-certificates \
curl \
default-libmysqlclient-dev \
default-mysql-client \
iputils-ping \
locales \
nmap \
openssh-client \
patch \
sshpass \
telnet \
vim \
wget"
ARG APT_MIRROR=http://mirrors.ustc.edu.cn
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core-apt \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=core-apt \
sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& apt-get update \
&& apt-get -y install --no-install-recommends ${DEPENDENCIES} \
&& apt-get -y install --no-install-recommends ${TOOLS} \
&& mkdir -p /root/.ssh/ \
&& echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null\n\tCiphers +aes128-cbc\n\tKexAlgorithms +diffie-hellman-group1-sha1\n\tHostKeyAlgorithms +ssh-rsa" > /root/.ssh/config \
&& echo "no" | dpkg-reconfigure dash \
&& echo "zh_CN.UTF-8" | dpkg-reconfigure locales \
&& sed -i "s@# export @export @g" ~/.bashrc \
&& sed -i "s@# alias @alias @g" ~/.bashrc
COPY --from=stage-2 /opt/py3 /opt/py3
COPY --from=stage-1 /opt/jumpserver/release/jumpserver /opt/jumpserver
WORKDIR /opt/jumpserver
ARG VERSION
ENV VERSION=$VERSION
VOLUME /opt/jumpserver/data
EXPOSE 8080
ENTRYPOINT ["./entrypoint.sh"]

View File

@@ -1,5 +1,52 @@
ARG VERSION
FROM registry.fit2cloud.com/jumpserver/xpack:${VERSION} as build-xpack
FROM registry.fit2cloud.com/jumpserver/core-ce:${VERSION}
FROM registry.fit2cloud.com/jumpserver/xpack:${VERSION} AS build-xpack
FROM python:3.11-slim-bullseye AS build-core
ARG BUILD_DEPENDENCIES=" \
g++"
ARG APT_MIRROR=http://mirrors.ustc.edu.cn
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
set -ex \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
&& echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \
&& sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \
&& echo "no" | dpkg-reconfigure dash
WORKDIR /opt/jumpserver
ARG PIP_MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple
RUN --mount=type=cache,target=/root/.cache,sharing=locked,id=core \
--mount=type=bind,source=poetry.lock,target=/opt/jumpserver/poetry.lock \
--mount=type=bind,source=pyproject.toml,target=/opt/jumpserver/pyproject.toml \
set -ex \
&& python3 -m venv /opt/py3 \
&& pip install poetry -i ${PIP_MIRROR} \
&& poetry config virtualenvs.create false \
&& . /opt/py3/bin/activate \
&& poetry install --only xpack
FROM registry.fit2cloud.com/jumpserver/core:${VERSION}-ce
ARG TARGETARCH
ARG TOOLS=" \
curl \
iputils-ping \
netcat-openbsd \
nmap \
telnet \
vim \
wget"
ARG APT_MIRROR=http://mirrors.ustc.edu.cn
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
set -ex \
&& apt-get update \
&& apt-get -y install --no-install-recommends ${TOOLS}
COPY --from=build-core /opt/py3 /opt/py3
COPY --from=build-xpack /opt/xpack /opt/jumpserver/apps/xpack

207
README.md
View File

@@ -1,125 +1,112 @@
<p align="center">
<a href="https://jumpserver.org"><img src="https://download.jumpserver.org/images/jumpserver-logo.svg" alt="JumpServer" width="300" /></a>
</p>
<h3 align="center">广受欢迎的开源堡垒机</h3>
<div align="center">
<a name="readme-top"></a>
<a href="https://jumpserver.org/index-en.html"><img src="https://download.jumpserver.org/images/jumpserver-logo.svg" alt="JumpServer" width="300" /></a>
## An open-source PAM tool (Bastion Host)
<p align="center">
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://img.shields.io/github/license/jumpserver/jumpserver" alt="License: GPLv3"></a>
<a href="https://hub.docker.com/u/jumpserver"><img src="https://img.shields.io/docker/pulls/jumpserver/jms_all.svg" alt="Docker pulls"></a>
<a href="https://github.com/jumpserver/jumpserver/releases/latest"><img src="https://img.shields.io/github/v/release/jumpserver/jumpserver" alt="Latest release"></a>
<a href="https://github.com/jumpserver/jumpserver"><img src="https://img.shields.io/github/stars/jumpserver/jumpserver?color=%231890FF&style=flat-square" alt="Stars"></a>
</p>
[![][license-shield]][license-link]
[![][discord-shield]][discord-link]
[![][docker-shield]][docker-link]
[![][github-release-shield]][github-release-link]
[![][github-stars-shield]][github-stars-link]
**English** · [简体中文](./README.zh-CN.md) · [Documents][docs-link] · [Report Bug][github-issues-link] · [Request Feature][github-issues-link]
</div>
<br/>
## What is JumpServer?
JumpServer is an open-source Privileged Access Management (PAM) tool that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and Remote App endpoints through a web browser.
![JumpServer Overview](https://github.com/jumpserver/jumpserver/assets/41712985/eb9e6f39-3911-4d4a-bca9-aa50cc3b761d)
## Screenshots
<table style="border-collapse: collapse; border: 1px solid black;">
<tr>
<td style="padding: 5px;background-color:#fff;"><img src= "https://github.com/jumpserver/jumpserver/assets/32935519/99fabe5b-0475-4a53-9116-4c370a1426c4" alt="JumpServer Console" /></td>
<td style="padding: 5px;background-color:#fff;"><img src= "https://github.com/jumpserver/jumpserver/assets/32935519/a424d731-1c70-4108-a7d8-5bbf387dda9a" alt="JumpServer Audits" /></td>
</tr>
<tr>
<td style="padding: 5px;background-color:#fff;"><img src= "https://github.com/jumpserver/jumpserver/assets/32935519/393d2c27-a2d0-4dea-882d-00ed509e00c9" alt="JumpServer Workbench" /></td>
<td style="padding: 5px;background-color:#fff;"><img src= "https://github.com/jumpserver/jumpserver/assets/32935519/3a2611cd-8902-49b8-b82b-2a6dac851f3e" alt="JumpServer Settings" /></td>
</tr>
<tr>
<td style="padding: 5px;background-color:#fff;"><img src= "https://github.com/jumpserver/jumpserver/assets/32935519/1e236093-31f7-4563-8eb1-e36d865f1568" alt="JumpServer SSH" /></td>
<td style="padding: 5px;background-color:#fff;"><img src= "https://github.com/jumpserver/jumpserver/assets/32935519/69373a82-f7ab-41e8-b763-bbad2ba52167" alt="JumpServer RDP" /></td>
</tr>
<tr>
<td style="padding: 5px;background-color:#fff;"><img src= "https://github.com/jumpserver/jumpserver/assets/32935519/5bed98c6-cbe8-4073-9597-d53c69dc3957" alt="JumpServer K8s" /></td>
<td style="padding: 5px;background-color:#fff;"><img src= "https://github.com/jumpserver/jumpserver/assets/32935519/b80ad654-548f-42bc-ba3d-c1cfdf1b46d6" alt="JumpServer DB" /></td>
</tr>
</table>
## Quick Start
Prepare a clean Linux Server ( 64bit, >= 4c8g )
```
curl -sSL https://github.com/jumpserver/jumpserver/releases/latest/download/quick_start.sh | bash
```
Access JumpServer in your browser at `http://your-ip/`, `admin`/`admin`
## Components
JumpServer consists of multiple key components, which collectively form the functional framework of JumpServer, providing users with comprehensive capabilities for operations management and security control.
| Project | Status | Description |
|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| [Lina](https://github.com/jumpserver/lina) | <a href="https://github.com/jumpserver/lina/releases"><img alt="Lina release" src="https://img.shields.io/github/release/jumpserver/lina.svg" /></a> | JumpServer Web UI |
| [Luna](https://github.com/jumpserver/luna) | <a href="https://github.com/jumpserver/luna/releases"><img alt="Luna release" src="https://img.shields.io/github/release/jumpserver/luna.svg" /></a> | JumpServer Web Terminal |
| [KoKo](https://github.com/jumpserver/koko) | <a href="https://github.com/jumpserver/koko/releases"><img alt="Koko release" src="https://img.shields.io/github/release/jumpserver/koko.svg" /></a> | JumpServer Character Protocol Connector |
| [Lion](https://github.com/jumpserver/lion) | <a href="https://github.com/jumpserver/lion/releases"><img alt="Lion release" src="https://img.shields.io/github/release/jumpserver/lion.svg" /></a> | JumpServer Graphical Protocol Connector |
| [Chen](https://github.com/jumpserver/chen) | <a href="https://github.com/jumpserver/chen/releases"><img alt="Chen release" src="https://img.shields.io/github/release/jumpserver/chen.svg" /> | JumpServer Web DB |
| [Razor](https://github.com/jumpserver/razor) | <img alt="Chen" src="https://img.shields.io/badge/release-private-red" /> | JumpServer RDP Proxy Connector |
| [Tinker](https://github.com/jumpserver/tinker) | <img alt="Tinker" src="https://img.shields.io/badge/release-private-red" /> | JumpServer Remote Application Connector (Windows) |
| [Panda](https://github.com/jumpserver/Panda) | <img alt="Panda" src="https://img.shields.io/badge/release-private-red" /> | JumpServer Remote Application Connector (Linux) |
| [Magnus](https://github.com/jumpserver/magnus) | <img alt="Magnus" src="https://img.shields.io/badge/release-private-red" /> | JumpServer Database Proxy Connector |
<p align="center">
9 年时间,倾情投入,用心做好一款开源堡垒机。
</p>
------------------------------
JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。
## Contributing
JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型的资产,包括:
Welcome to submit PR to contribute. Please refer to [CONTRIBUTING.md][contributing-link] for guidelines.
- **SSH**: Linux / Unix / 网络设备 等;
- **Windows**: Web 方式连接 / 原生 RDP 连接;
- **数据库**: MySQL / MariaDB / PostgreSQL / Oracle / SQLServer / ClickHouse 等;
- **NoSQL**: Redis / MongoDB 等;
- **GPT**: ChatGPT 等;
- **云服务**: Kubernetes / VMware vSphere 等;
- **Web 站点**: 各类系统的 Web 管理后台;
- **应用**: 通过 Remote App 连接各类应用。
## Security
## 产品特色
JumpServer is a mission critical product. Please refer to the Basic Security Recommendations for installation and deployment. If you encounter any security-related issues, please contact us directly:
- **开源**: 零门槛,线上快速获取和安装;
- **无插件**: 仅需浏览器,极致的 Web Terminal 使用体验;
- **分布式**: 支持分布式部署和横向扩展,轻松支持大规模并发访问;
- **多云支持**: 一套系统,同时管理不同云上面的资产;
- **多租户**: 一套系统,多个子公司或部门同时使用;
- **云端存储**: 审计录像云端存储,永不丢失;
- Email: support@fit2cloud.com
## UI 展示
![UI展示](https://docs.jumpserver.org/zh/v3/img/dashboard.png)
## 在线体验
- 环境地址:<https://demo.jumpserver.org/>
| :warning: 注意 |
|:-----------------------------|
| 该环境仅作体验目的使用,我们会定时清理、重置数据! |
| 请勿修改体验环境用户的密码! |
| 请勿在环境中添加业务生产环境地址、用户名密码等敏感信息! |
## 快速开始
- [快速入门](https://docs.jumpserver.org/zh/v3/quick_start/)
- [产品文档](https://docs.jumpserver.org)
- [在线学习](https://edu.fit2cloud.com/page/2635362)
- [知识库](https://kb.fit2cloud.com/categories/jumpserver)
## 案例研究
- [腾讯音乐娱乐集团基于JumpServer的安全运维审计解决方案](https://blog.fit2cloud.com/?p=a04cdf0d-6704-4d18-9b40-9180baecd0e2)
- [腾讯海外游戏基于JumpServer构建游戏安全运营能力](https://blog.fit2cloud.com/?p=3704)
- [万华化学通过JumpServer管理全球化分布式IT资产并且实现与云管平台的联动](https://blog.fit2cloud.com/?p=3504)
- [雪花啤酒JumpServer堡垒机使用体会](https://blog.fit2cloud.com/?p=3412)
- [顺丰科技JumpServer 堡垒机护航顺丰科技超大规模资产安全运维](https://blog.fit2cloud.com/?p=1147)
- [沐瞳游戏通过JumpServer管控多项目分布式资产](https://blog.fit2cloud.com/?p=3213)
- [携程JumpServer 堡垒机部署与运营实战](https://blog.fit2cloud.com/?p=851)
- [大智慧JumpServer 堡垒机让“大智慧”的混合 IT 运维更智慧](https://blog.fit2cloud.com/?p=882)
- [小红书JumpServer 堡垒机大规模资产跨版本迁移之路](https://blog.fit2cloud.com/?p=516)
- [中手游JumpServer堡垒机助力中手游提升多云环境下安全运维能力](https://blog.fit2cloud.com/?p=732)
- [中通快递JumpServer主机安全运维实践](https://blog.fit2cloud.com/?p=708)
- [东方明珠JumpServer高效管控异构化、分布式云端资产](https://blog.fit2cloud.com/?p=687)
- [江苏农信JumpServer堡垒机助力行业云安全运维](https://blog.fit2cloud.com/?p=666)
## 社区交流
如果您在使用过程中有任何疑问或对建议,欢迎提交 [GitHub Issue](https://github.com/jumpserver/jumpserver/issues/new/choose)。
您也可以到我们的 [社区论坛](https://bbs.fit2cloud.com/c/js/5) 当中进行交流沟通。
### 参与贡献
欢迎提交 PR 参与贡献。 参考 [CONTRIBUTING.md](https://github.com/jumpserver/jumpserver/blob/dev/CONTRIBUTING.md)
## 组件项目
| 项目 | 状态 | 描述 |
|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|
| [Lina](https://github.com/jumpserver/lina) | <a href="https://github.com/jumpserver/lina/releases"><img alt="Lina release" src="https://img.shields.io/github/release/jumpserver/lina.svg" /></a> | JumpServer Web UI 项目 |
| [Luna](https://github.com/jumpserver/luna) | <a href="https://github.com/jumpserver/luna/releases"><img alt="Luna release" src="https://img.shields.io/github/release/jumpserver/luna.svg" /></a> | JumpServer Web Terminal 项目 |
| [KoKo](https://github.com/jumpserver/koko) | <a href="https://github.com/jumpserver/koko/releases"><img alt="Koko release" src="https://img.shields.io/github/release/jumpserver/koko.svg" /></a> | JumpServer 字符协议 Connector 项目 |
| [Lion](https://github.com/jumpserver/lion-release) | <a href="https://github.com/jumpserver/lion-release/releases"><img alt="Lion release" src="https://img.shields.io/github/release/jumpserver/lion-release.svg" /></a> | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) |
| [Razor](https://github.com/jumpserver/razor) | <img alt="Chen" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer RDP 代理 Connector 项目 |
| [Tinker](https://github.com/jumpserver/tinker) | <img alt="Tinker" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer 远程应用 Connector 项目 (Windows) |
| [Panda](https://github.com/jumpserver/Panda) | <img alt="Panda" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer 远程应用 Connector 项目 (Linux) |
| [Magnus](https://github.com/jumpserver/magnus-release) | <a href="https://github.com/jumpserver/magnus-release/releases"><img alt="Magnus release" src="https://img.shields.io/github/release/jumpserver/magnus-release.svg" /> | JumpServer 数据库代理 Connector 项目 |
| [Chen](https://github.com/jumpserver/chen-release) | <a href="https://github.com/jumpserver/chen-release/releases"><img alt="Chen release" src="https://img.shields.io/github/release/jumpserver/chen-release.svg" /> | JumpServer Web DB 项目,替代原来的 OmniDB |
| [Kael](https://github.com/jumpserver/kael) | <a href="https://github.com/jumpserver/kael/releases"><img alt="Kael release" src="https://img.shields.io/github/release/jumpserver/kael.svg" /> | JumpServer 连接 GPT 资产的组件项目 |
| [Wisp](https://github.com/jumpserver/wisp) | <a href="https://github.com/jumpserver/wisp/releases"><img alt="Magnus release" src="https://img.shields.io/github/release/jumpserver/wisp.svg" /> | JumpServer 各系统终端组件和 Core API 通信的组件项目 |
| [Clients](https://github.com/jumpserver/clients) | <a href="https://github.com/jumpserver/clients/releases"><img alt="Clients release" src="https://img.shields.io/github/release/jumpserver/clients.svg" /> | JumpServer 客户端 项目 |
| [Installer](https://github.com/jumpserver/installer) | <a href="https://github.com/jumpserver/installer/releases"><img alt="Installer release" src="https://img.shields.io/github/release/jumpserver/installer.svg" /> | JumpServer 安装包 项目 |
## 安全说明
JumpServer是一款安全产品请参考 [基本安全建议](https://docs.jumpserver.org/zh/master/install/install_security/)
进行安装部署。如果您发现安全相关问题,请直接联系我们:
- 邮箱support@fit2cloud.com
- 电话400-052-0755
## License & Copyright
## License
Copyright (c) 2014-2024 飞致云 FIT2CLOUD, All rights reserved.
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
https://www.gnu.org/licenses/gpl-3.0.html
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "
AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an " AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
<!-- JumpServer official link -->
[docs-link]: https://en-docs.jumpserver.org/
[discord-link]: https://discord.com/invite/jcM5tKWJ
[contributing-link]: https://github.com/jumpserver/jumpserver/blob/dev/CONTRIBUTING.md
<!-- JumpServer Other link-->
[license-link]: https://www.gnu.org/licenses/gpl-3.0.html
[docker-link]: https://hub.docker.com/u/jumpserver
[github-release-link]: https://github.com/jumpserver/jumpserver/releases/latest
[github-stars-link]: https://github.com/jumpserver/jumpserver
[github-issues-link]: https://github.com/jumpserver/jumpserver/issues
<!-- Shield link-->
[github-release-shield]: https://img.shields.io/github/v/release/jumpserver/jumpserver
[github-stars-shield]: https://img.shields.io/github/stars/jumpserver/jumpserver?color=%231890FF&style=flat-square
[docker-shield]: https://img.shields.io/docker/pulls/jumpserver/jms_all.svg
[license-shield]: https://img.shields.io/github/license/jumpserver/jumpserver
[discord-shield]: https://img.shields.io/discord/1194233267294052363?style=flat&logo=discord&logoColor=%23f5f5f5&labelColor=%235462eb&color=%235462eb
<!-- Image link -->

125
README.zh-CN.md Normal file
View File

@@ -0,0 +1,125 @@
<p align="center">
<a href="https://jumpserver.org"><img src="https://download.jumpserver.org/images/jumpserver-logo.svg" alt="JumpServer" width="300" /></a>
</p>
<h3 align="center">广受欢迎的开源堡垒机</h3>
<p align="center">
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://img.shields.io/github/license/jumpserver/jumpserver" alt="License: GPLv3"></a>
<a href="https://hub.docker.com/u/jumpserver"><img src="https://img.shields.io/docker/pulls/jumpserver/jms_all.svg" alt="Docker pulls"></a>
<a href="https://github.com/jumpserver/jumpserver/releases/latest"><img src="https://img.shields.io/github/v/release/jumpserver/jumpserver" alt="Latest release"></a>
<a href="https://github.com/jumpserver/jumpserver"><img src="https://img.shields.io/github/stars/jumpserver/jumpserver?color=%231890FF&style=flat-square" alt="Stars"></a>
</p>
<p align="center">
9 年时间,倾情投入,用心做好一款开源堡垒机。
</p>
------------------------------
JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。
JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型的资产,包括:
- **SSH**: Linux / Unix / 网络设备 等;
- **Windows**: Web 方式连接 / 原生 RDP 连接;
- **数据库**: MySQL / MariaDB / PostgreSQL / Oracle / SQLServer / ClickHouse 等;
- **NoSQL**: Redis / MongoDB 等;
- **GPT**: ChatGPT 等;
- **云服务**: Kubernetes / VMware vSphere 等;
- **Web 站点**: 各类系统的 Web 管理后台;
- **应用**: 通过 Remote App 连接各类应用。
## 产品特色
- **开源**: 零门槛,线上快速获取和安装;
- **无插件**: 仅需浏览器,极致的 Web Terminal 使用体验;
- **分布式**: 支持分布式部署和横向扩展,轻松支持大规模并发访问;
- **多云支持**: 一套系统,同时管理不同云上面的资产;
- **多租户**: 一套系统,多个子公司或部门同时使用;
- **云端存储**: 审计录像云端存储,永不丢失;
## UI 展示
![UI展示](https://docs.jumpserver.org/zh/v3/img/dashboard.png)
## 在线体验
- 环境地址:<https://demo.jumpserver.org/>
| :warning: 注意 |
|:-----------------------------|
| 该环境仅作体验目的使用,我们会定时清理、重置数据! |
| 请勿修改体验环境用户的密码! |
| 请勿在环境中添加业务生产环境地址、用户名密码等敏感信息! |
## 快速开始
- [快速入门](https://docs.jumpserver.org/zh/v3/quick_start/)
- [产品文档](https://docs.jumpserver.org)
- [在线学习](https://edu.fit2cloud.com/page/2635362)
- [知识库](https://kb.fit2cloud.com/categories/jumpserver)
## 案例研究
- [腾讯音乐娱乐集团基于JumpServer的安全运维审计解决方案](https://blog.fit2cloud.com/?p=a04cdf0d-6704-4d18-9b40-9180baecd0e2)
- [腾讯海外游戏基于JumpServer构建游戏安全运营能力](https://blog.fit2cloud.com/?p=3704)
- [万华化学通过JumpServer管理全球化分布式IT资产并且实现与云管平台的联动](https://blog.fit2cloud.com/?p=3504)
- [雪花啤酒JumpServer堡垒机使用体会](https://blog.fit2cloud.com/?p=3412)
- [顺丰科技JumpServer 堡垒机护航顺丰科技超大规模资产安全运维](https://blog.fit2cloud.com/?p=1147)
- [沐瞳游戏通过JumpServer管控多项目分布式资产](https://blog.fit2cloud.com/?p=3213)
- [携程JumpServer 堡垒机部署与运营实战](https://blog.fit2cloud.com/?p=851)
- [大智慧JumpServer 堡垒机让“大智慧”的混合 IT 运维更智慧](https://blog.fit2cloud.com/?p=882)
- [小红书JumpServer 堡垒机大规模资产跨版本迁移之路](https://blog.fit2cloud.com/?p=516)
- [中手游JumpServer堡垒机助力中手游提升多云环境下安全运维能力](https://blog.fit2cloud.com/?p=732)
- [中通快递JumpServer主机安全运维实践](https://blog.fit2cloud.com/?p=708)
- [东方明珠JumpServer高效管控异构化、分布式云端资产](https://blog.fit2cloud.com/?p=687)
- [江苏农信JumpServer堡垒机助力行业云安全运维](https://blog.fit2cloud.com/?p=666)
## 社区交流
如果您在使用过程中有任何疑问或对建议,欢迎提交 [GitHub Issue](https://github.com/jumpserver/jumpserver/issues/new/choose)。
您也可以到我们的 [社区论坛](https://bbs.fit2cloud.com/c/js/5) 当中进行交流沟通。
### 参与贡献
欢迎提交 PR 参与贡献。 参考 [CONTRIBUTING.md](https://github.com/jumpserver/jumpserver/blob/dev/CONTRIBUTING.md)
## 组件项目
| 项目 | 状态 | 描述 |
|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|
| [Lina](https://github.com/jumpserver/lina) | <a href="https://github.com/jumpserver/lina/releases"><img alt="Lina release" src="https://img.shields.io/github/release/jumpserver/lina.svg" /></a> | JumpServer Web UI 项目 |
| [Luna](https://github.com/jumpserver/luna) | <a href="https://github.com/jumpserver/luna/releases"><img alt="Luna release" src="https://img.shields.io/github/release/jumpserver/luna.svg" /></a> | JumpServer Web Terminal 项目 |
| [KoKo](https://github.com/jumpserver/koko) | <a href="https://github.com/jumpserver/koko/releases"><img alt="Koko release" src="https://img.shields.io/github/release/jumpserver/koko.svg" /></a> | JumpServer 字符协议 Connector 项目 |
| [Lion](https://github.com/jumpserver/lion-release) | <a href="https://github.com/jumpserver/lion-release/releases"><img alt="Lion release" src="https://img.shields.io/github/release/jumpserver/lion-release.svg" /></a> | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) |
| [Razor](https://github.com/jumpserver/razor) | <img alt="Chen" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer RDP 代理 Connector 项目 |
| [Tinker](https://github.com/jumpserver/tinker) | <img alt="Tinker" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer 远程应用 Connector 项目 (Windows) |
| [Panda](https://github.com/jumpserver/Panda) | <img alt="Panda" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer 远程应用 Connector 项目 (Linux) |
| [Magnus](https://github.com/jumpserver/magnus-release) | <a href="https://github.com/jumpserver/magnus-release/releases"><img alt="Magnus release" src="https://img.shields.io/github/release/jumpserver/magnus-release.svg" /> | JumpServer 数据库代理 Connector 项目 |
| [Chen](https://github.com/jumpserver/chen-release) | <a href="https://github.com/jumpserver/chen-release/releases"><img alt="Chen release" src="https://img.shields.io/github/release/jumpserver/chen-release.svg" /> | JumpServer Web DB 项目,替代原来的 OmniDB |
| [Kael](https://github.com/jumpserver/kael) | <a href="https://github.com/jumpserver/kael/releases"><img alt="Kael release" src="https://img.shields.io/github/release/jumpserver/kael.svg" /> | JumpServer 连接 GPT 资产的组件项目 |
| [Wisp](https://github.com/jumpserver/wisp) | <a href="https://github.com/jumpserver/wisp/releases"><img alt="Magnus release" src="https://img.shields.io/github/release/jumpserver/wisp.svg" /> | JumpServer 各系统终端组件和 Core API 通信的组件项目 |
| [Clients](https://github.com/jumpserver/clients) | <a href="https://github.com/jumpserver/clients/releases"><img alt="Clients release" src="https://img.shields.io/github/release/jumpserver/clients.svg" /> | JumpServer 客户端 项目 |
| [Installer](https://github.com/jumpserver/installer) | <a href="https://github.com/jumpserver/installer/releases"><img alt="Installer release" src="https://img.shields.io/github/release/jumpserver/installer.svg" /> | JumpServer 安装包 项目 |
## 安全说明
JumpServer是一款安全产品请参考 [基本安全建议](https://docs.jumpserver.org/zh/master/install/install_security/)
进行安装部署。如果您发现安全相关问题,请直接联系我们:
- 邮箱support@fit2cloud.com
- 电话400-052-0755
## License & Copyright
Copyright (c) 2014-2024 飞致云 FIT2CLOUD, All rights reserved.
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
https://www.gnu.org/licenses/gpl-3.0.html
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "
AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.

View File

@@ -1,94 +0,0 @@
<p align="center"><a href="https://jumpserver.org"><img src="https://download.jumpserver.org/images/jumpserver-logo.svg" alt="JumpServer" width="300" /></a></p>
<h3 align="center">Open Source Bastion Host</h3>
<p align="center">
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://img.shields.io/github/license/jumpserver/jumpserver" alt="License: GPLv3"></a>
<a href="https://shields.io/github/downloads/jumpserver/jumpserver/total"><img src="https://shields.io/github/downloads/jumpserver/jumpserver/total" alt=" release"></a>
<a href="https://hub.docker.com/u/jumpserver"><img src="https://img.shields.io/docker/pulls/jumpserver/jms_all.svg" alt="Codacy"></a>
<a href="https://github.com/jumpserver/jumpserver"><img src="https://img.shields.io/github/stars/jumpserver/jumpserver?color=%231890FF&style=flat-square" alt="Stars"></a>
</p>
JumpServer is the world's first open-source Bastion Host and is licensed under the GPLv3. It is a 4A-compliant professional operation and maintenance security audit system.
JumpServer uses Python / Django for development, follows Web 2.0 specifications, and is equipped with an industry-leading Web Terminal solution that provides a beautiful user interface and great user experience
JumpServer adopts a distributed architecture to support multi-branch deployment across multiple cross-regional areas. The central node provides APIs, and login nodes are deployed in each branch. It can be scaled horizontally without concurrency restrictions.
Change the world by taking every little step
----
### Advantages
- Open Source: huge transparency and free to access with quick installation process.
- Distributed: support large-scale concurrent access with ease.
- No Plugin required: all you need is a browser, the ultimate Web Terminal experience.
- Multi-Cloud supported: a unified system to manage assets on different clouds at the same time
- Cloud storage: audit records are stored in the cloud. Data lost no more!
- Multi-Tenant system: multiple subsidiary companies or departments access the same system simultaneously.
- Many applications supported: link to databases, windows remote applications, and Kubernetes cluster, etc.
### JumpServer Component Projects
- [Lina](https://github.com/jumpserver/lina) JumpServer Web UI
- [Luna](https://github.com/jumpserver/luna) JumpServer Web Terminal
- [KoKo](https://github.com/jumpserver/koko) JumpServer Character protocaol Connector, replace original Python Version [Coco](https://github.com/jumpserver/coco)
- [Lion](https://github.com/jumpserver/lion-release) JumpServer Graphics protocol Connectorrely on [Apache Guacamole](https://guacamole.apache.org/)
### Contribution
If you have any good ideas or helping us to fix bugs, please submit a Pull Request and accept our thanks :)
Thanks to the following contributors for making JumpServer better everyday!
<a href="https://github.com/jumpserver/jumpserver/graphs/contributors">
<img src="https://contrib.rocks/image?repo=jumpserver/jumpserver" />
</a>
<a href="https://github.com/jumpserver/koko/graphs/contributors">
<img src="https://contrib.rocks/image?repo=jumpserver/koko" />
</a>
<a href="https://github.com/jumpserver/lina/graphs/contributors">
<img src="https://contrib.rocks/image?repo=jumpserver/lina" />
</a>
<a href="https://github.com/jumpserver/luna/graphs/contributors">
<img src="https://contrib.rocks/image?repo=jumpserver/luna" />
</a>
### Thanks to
- [Apache Guacamole](https://guacamole.apache.org/) Web page connection RDP, SSH, VNC protocol equipment. JumpServer graphical connection dependent.
- [OmniDB](https://omnidb.org/) Web page connection to databases. JumpServer Web database dependent.
### JumpServer Enterprise Version
- [Apply for it](https://jinshuju.net/f/kyOYpi)
### Case Study
- [JumpServer 堡垒机护航顺丰科技超大规模资产安全运维](https://blog.fit2cloud.com/?p=1147)
- [JumpServer 堡垒机让“大智慧”的混合 IT 运维更智慧](https://blog.fit2cloud.com/?p=882)
- [携程 JumpServer 堡垒机部署与运营实战](https://blog.fit2cloud.com/?p=851)
- [小红书的JumpServer堡垒机大规模资产跨版本迁移之路](https://blog.fit2cloud.com/?p=516)
- [JumpServer堡垒机助力中手游提升多云环境下安全运维能力](https://blog.fit2cloud.com/?p=732)
- [中通快递JumpServer主机安全运维实践](https://blog.fit2cloud.com/?p=708)
- [东方明珠JumpServer高效管控异构化、分布式云端资产](https://blog.fit2cloud.com/?p=687)
- [江苏农信JumpServer堡垒机助力行业云安全运维](https://blog.fit2cloud.com/?p=666)。
### For safety instructions
JumpServer is a security product. Please refer to [Basic Security Recommendations](https://docs.jumpserver.org/zh/master/install/install_security/) for deployment and installation.
If you find a security problem, please contact us directly
- ibuler@fit2cloud.com
- support@fit2cloud.com
- 400-052-0755
### License & Copyright
Copyright (c) 2014-2022 FIT2CLOUD Tech, Inc., All rights reserved.
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
https://www.gnu.org/licenses/gpl-3.0.htmll
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

View File

@@ -18,9 +18,8 @@ __all__ = [
class AccountBackupPlanViewSet(OrgBulkModelViewSet):
model = AccountBackupAutomation
filter_fields = ('name',)
search_fields = filter_fields
ordering = ('name',)
filterset_fields = ('name',)
search_fields = filterset_fields
serializer_class = serializers.AccountBackupSerializer

View File

@@ -20,8 +20,8 @@ __all__ = [
class AutomationAssetsListApi(generics.ListAPIView):
model = BaseAutomation
serializer_class = serializers.AutomationAssetsSerializer
filter_fields = ("name", "address")
search_fields = filter_fields
filterset_fields = ("name", "address")
search_fields = filterset_fields
def get_object(self):
pk = self.kwargs.get('pk')

View File

@@ -6,9 +6,12 @@ from rest_framework.response import Response
from accounts import serializers
from accounts.const import AutomationTypes
from accounts.filters import ChangeSecretRecordFilterSet
from accounts.models import ChangeSecretAutomation, ChangeSecretRecord
from accounts.tasks import execute_automation_record_task
from authentication.permissions import UserConfirmation, ConfirmType
from orgs.mixins.api import OrgBulkModelViewSet, OrgGenericViewSet
from rbac.permissions import RBACPermission
from .base import (
AutomationAssetsListApi, AutomationRemoveAssetApi, AutomationAddAssetApi,
AutomationNodeAddRemoveApi, AutomationExecutionViewSet
@@ -24,35 +27,54 @@ __all__ = [
class ChangeSecretAutomationViewSet(OrgBulkModelViewSet):
model = ChangeSecretAutomation
filter_fields = ('name', 'secret_type', 'secret_strategy')
search_fields = filter_fields
filterset_fields = ('name', 'secret_type', 'secret_strategy')
search_fields = filterset_fields
serializer_class = serializers.ChangeSecretAutomationSerializer
class ChangeSecretRecordViewSet(mixins.ListModelMixin, OrgGenericViewSet):
serializer_class = serializers.ChangeSecretRecordSerializer
filterset_fields = ('asset_id', 'execution_id')
filterset_class = ChangeSecretRecordFilterSet
search_fields = ('asset__address',)
tp = AutomationTypes.change_secret
serializer_classes = {
'default': serializers.ChangeSecretRecordSerializer,
'secret': serializers.ChangeSecretRecordViewSecretSerializer,
}
rbac_perms = {
'execute': 'accounts.add_changesecretexecution',
'secret': 'accounts.view_changesecretrecord',
}
def get_permissions(self):
if self.action == 'secret':
self.permission_classes = [
RBACPermission,
UserConfirmation.require(ConfirmType.MFA)
]
return super().get_permissions()
def get_queryset(self):
return ChangeSecretRecord.objects.all()
@action(methods=['post'], detail=False, url_path='execute')
def execute(self, request, *args, **kwargs):
record_id = request.data.get('record_id')
record = self.get_queryset().filter(pk=record_id)
if not record:
record_ids = request.data.get('record_ids')
records = self.get_queryset().filter(id__in=record_ids)
execution_count = records.values_list('execution_id', flat=True).distinct().count()
if execution_count != 1:
return Response(
{'detail': 'record not found'},
status=status.HTTP_404_NOT_FOUND
{'detail': 'Only one execution is allowed to execute'},
status=status.HTTP_400_BAD_REQUEST
)
task = execute_automation_record_task.delay(record_id, self.tp)
task = execute_automation_record_task.delay(record_ids, self.tp)
return Response({'task': task.id}, status=status.HTTP_200_OK)
@action(methods=['get'], detail=True, url_path='secret')
def secret(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
class ChangSecretExecutionViewSet(AutomationExecutionViewSet):
rbac_perms = (

View File

@@ -20,8 +20,8 @@ __all__ = [
class GatherAccountsAutomationViewSet(OrgBulkModelViewSet):
model = GatherAccountsAutomation
filter_fields = ('name',)
search_fields = filter_fields
filterset_fields = ('name',)
search_fields = filterset_fields
serializer_class = serializers.GatherAccountAutomationSerializer

View File

@@ -20,8 +20,8 @@ __all__ = [
class PushAccountAutomationViewSet(OrgBulkModelViewSet):
model = PushAccountAutomation
filter_fields = ('name', 'secret_type', 'secret_strategy')
search_fields = filter_fields
filterset_fields = ('name', 'secret_type', 'secret_strategy')
search_fields = filterset_fields
serializer_class = serializers.PushAccountAutomationSerializer

View File

@@ -4,6 +4,7 @@ from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'
verbose_name = 'App Accounts'
def ready(self):
from . import signal_handlers # noqa

View File

@@ -3,10 +3,11 @@ import time
from collections import defaultdict, OrderedDict
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from xlsxwriter import Workbook
from accounts.const.automation import AccountBackupType
from accounts.const import AccountBackupType
from accounts.models.automations.backup_account import AccountBackupAutomation
from accounts.notifications import AccountBackupExecutionTaskMsg, AccountBackupByObjStorageExecutionTaskMsg
from accounts.serializers import AccountSecretSerializer
@@ -17,7 +18,7 @@ from terminal.models.component.storage import ReplayStorage
from users.models import User
PATH = os.path.join(os.path.dirname(settings.BASE_DIR), 'tmp')
split_help_text = _('The account key will be split into two parts and sent')
class RecipientsNotFound(Exception):
pass
@@ -115,8 +116,8 @@ class AssetAccountHandler(BaseAccountHandler):
data = AccountSecretSerializer(_accounts, many=True).data
cls.handler_secret(data, section)
data_map.update(cls.add_rows(data, header_fields, sheet_name))
print('\n\033[33m- 共备份 {} 条账号\033[0m'.format(accounts.count()))
number_of_backup_accounts = _('Number of backup accounts')
print('\n\033[33m- {}: {}\033[0m'.format(number_of_backup_accounts, accounts.count()))
return data_map
@@ -127,9 +128,10 @@ class AccountBackupHandler:
self.is_frozen = False # 任务状态冻结标志
def create_excel(self, section='complete'):
hint = _('Generating asset or application related backup information files')
print(
'\n'
'\033[32m>>> 正在生成资产或应用相关备份信息文件\033[0m'
f'\033[32m>>> {hint}\033[0m'
''
)
# Print task start date
@@ -151,7 +153,9 @@ class AccountBackupHandler:
wb.close()
files.append(filename)
timedelta = round((time.time() - time_start), 2)
print('创建备份文件完成: 用时 {}s'.format(timedelta))
time_cost = _('Time cost')
file_created = _('Backup file creation completed')
print('{}: {} {}s'.format(file_created, time_cost, timedelta))
return files
def send_backup_mail(self, files, recipients):
@@ -160,7 +164,7 @@ class AccountBackupHandler:
recipients = User.objects.filter(id__in=list(recipients))
print(
'\n'
'\033[32m>>> 开始发送备份邮件\033[0m'
f'\033[32m>>> {_("Start sending backup emails")}\033[0m'
''
)
plan_name = self.plan_name
@@ -172,7 +176,8 @@ class AccountBackupHandler:
encrypt_and_compress_zip_file(attachment, user.secret_key, files)
attachment_list = [attachment, ]
AccountBackupExecutionTaskMsg(plan_name, user).publish(attachment_list)
print('邮件已发送至{}({})'.format(user, user.email))
email_sent_to = _('Email sent to')
print('{} {}({})'.format(email_sent_to, user, user.email))
for file in files:
os.remove(file)
@@ -182,20 +187,22 @@ class AccountBackupHandler:
recipients = ReplayStorage.objects.filter(id__in=list(recipients))
print(
'\n'
'\033[32m>>> 开始发送备份文件到sftp服务器\033[0m'
'\033[32m>>> 📃 ---> sftp \033[0m'
''
)
plan_name = self.plan_name
encrypt_file = _('Encrypting files using encryption password')
for rec in recipients:
attachment = os.path.join(PATH, f'{plan_name}-{local_now_filename()}-{time.time()}.zip')
if password:
print('\033[32m>>> 使用加密密码对文件进行加密中\033[0m')
print(f'\033[32m>>> {encrypt_file}\033[0m')
encrypt_and_compress_zip_file(attachment, password, files)
else:
zip_files(attachment, files)
attachment_list = attachment
AccountBackupByObjStorageExecutionTaskMsg(plan_name, rec).publish(attachment_list)
print('备份文件将发送至{}({})'.format(rec.name, rec.id))
file_sent_to = _('The backup file will be sent to')
print('{}: {}({})'.format(file_sent_to, rec.name, rec.id))
for file in files:
os.remove(file)
@@ -203,14 +210,15 @@ class AccountBackupHandler:
self.execution.reason = reason[:1024]
self.execution.is_success = is_success
self.execution.save()
print('\n已完成对任务状态的更新\n')
finish = _('Finish')
print(f'\n{finish}\n')
@staticmethod
def step_finished(is_success):
if is_success:
print('任务执行成功')
print(_('Success'))
else:
print('任务执行失败')
print(_('Failed'))
def _run(self):
is_success = False
@@ -223,8 +231,6 @@ class AccountBackupHandler:
self.backup_by_obj_storage()
except Exception as e:
self.is_frozen = True
print('任务执行被异常中断')
print('下面打印发生异常的 Traceback 信息 : ')
print(e)
error = str(e)
else:
@@ -239,15 +245,16 @@ class AccountBackupHandler:
zip_encrypt_password = AccountBackupAutomation.objects.get(id=object_id).zip_encrypt_password
obj_recipients_part_one = self.execution.snapshot.get('obj_recipients_part_one', [])
obj_recipients_part_two = self.execution.snapshot.get('obj_recipients_part_two', [])
no_assigned_sftp_server = _('The backup task has no assigned sftp server')
if not obj_recipients_part_one and not obj_recipients_part_two:
print(
'\n'
'\033[31m>>> 该备份任务未分配sftp服务器\033[0m'
f'\033[31m>>> {no_assigned_sftp_server}\033[0m'
''
)
raise RecipientsNotFound('Not Found Recipients')
if obj_recipients_part_one and obj_recipients_part_two:
print('\033[32m>>> 账号的密钥将被拆分成前后两部分发送\033[0m')
print(f'\033[32m>>> {split_help_text}\033[0m')
files = self.create_excel(section='front')
self.send_backup_obj_storage(files, obj_recipients_part_one, zip_encrypt_password)
@@ -259,17 +266,19 @@ class AccountBackupHandler:
self.send_backup_obj_storage(files, recipients, zip_encrypt_password)
def backup_by_email(self):
warn_text = _('The backup task has no assigned recipient')
recipients_part_one = self.execution.snapshot.get('recipients_part_one', [])
recipients_part_two = self.execution.snapshot.get('recipients_part_two', [])
if not recipients_part_one and not recipients_part_two:
print(
'\n'
'\033[31m>>> 该备份任务未分配收件人\033[0m'
f'\033[31m>>> {warn_text}\033[0m'
''
)
raise RecipientsNotFound('Not Found Recipients')
if recipients_part_one and recipients_part_two:
print('\033[32m>>> 账号的密钥将被拆分成前后两部分发送\033[0m')
print(f'\033[32m>>> {split_help_text}\033[0m')
files = self.create_excel(section='front')
self.send_backup_mail(files, recipients_part_one)
@@ -281,15 +290,18 @@ class AccountBackupHandler:
self.send_backup_mail(files, recipients)
def run(self):
print('任务开始: {}'.format(local_now_display()))
plan_start = _('Plan start')
plan_end = _('Plan end')
time_cost = _('Time cost')
error = _('An exception occurred during task execution')
print('{}: {}'.format(plan_start, local_now_display()))
time_start = time.time()
try:
self._run()
except Exception as e:
print('任务运行出现异常')
print('下面显示异常 Traceback 信息: ')
print(error)
print(e)
finally:
print('\n任务结束: {}'.format(local_now_display()))
print('\n{}: {}'.format(plan_end, local_now_display()))
timedelta = round((time.time() - time_start), 2)
print('用时: {}s'.format(timedelta))
print('{}: {}s'.format(time_cost, timedelta))

View File

@@ -3,6 +3,7 @@
import time
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from common.utils.timezone import local_now_display
from .handlers import AccountBackupHandler
@@ -19,7 +20,8 @@ class AccountBackupManager:
def do_run(self):
execution = self.execution
print('\n\033[33m# 账号备份计划正在执行\033[0m')
account_backup_execution_being_executed = _('The account backup plan is being executed')
print(f'\n\033[33m# {account_backup_execution_being_executed}\033[0m')
handler = AccountBackupHandler(execution)
handler.run()
@@ -32,9 +34,11 @@ class AccountBackupManager:
self.date_end = timezone.now()
print('\n\n' + '-' * 80)
print('计划执行结束 {}\n'.format(local_now_display()))
plan_execution_end = _('Plan execution end')
print('{} {}\n'.format(plan_execution_end, local_now_display()))
self.timedelta = self.time_end - self.time_start
print('用时: {}s'.format(self.timedelta))
time_cost = _('Time cost')
print('{}: {}s'.format(time_cost, self.timedelta))
self.execution.timedelta = self.timedelta
self.execution.save()

View File

@@ -13,11 +13,13 @@
login_password: "{{ jms_account.secret }}"
login_secret_type: "{{ jms_account.secret_type }}"
login_private_key_path: "{{ jms_account.private_key_path }}"
become: "{{ custom_become | default(False) }}"
become_method: "{{ custom_become_method | default('su') }}"
become_user: "{{ custom_become_user | default('') }}"
become_password: "{{ custom_become_password | default('') }}"
become_private_key_path: "{{ custom_become_private_key_path | default(None) }}"
become: "{{ jms_custom_become | default(False) }}"
become_method: "{{ jms_custom_become_method | default('su') }}"
become_user: "{{ jms_custom_become_user | default('') }}"
become_password: "{{ jms_custom_become_password | default('') }}"
become_private_key_path: "{{ jms_custom_become_private_key_path | default(None) }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}"
register: ping_info
delegate_to: localhost
@@ -29,11 +31,11 @@
login_port: "{{ jms_asset.port }}"
login_secret_type: "{{ jms_account.secret_type }}"
login_private_key_path: "{{ jms_account.private_key_path }}"
become: "{{ custom_become | default(False) }}"
become_method: "{{ custom_become_method | default('su') }}"
become_user: "{{ custom_become_user | default('') }}"
become_password: "{{ custom_become_password | default('') }}"
become_private_key_path: "{{ custom_become_private_key_path | default(None) }}"
become: "{{ jms_custom_become | default(False) }}"
become_method: "{{ jms_custom_become_method | default('su') }}"
become_user: "{{ jms_custom_become_user | default('') }}"
become_password: "{{ jms_custom_become_password | default('') }}"
become_private_key_path: "{{ jms_custom_become_private_key_path | default(None) }}"
name: "{{ account.username }}"
password: "{{ account.secret }}"
commands: "{{ params.commands }}"
@@ -54,4 +56,6 @@
become_user: "{{ account.become.ansible_user | default('') }}"
become_password: "{{ account.become.ansible_password | default('') }}"
become_private_key_path: "{{ account.become.ansible_ssh_private_key_file | default(None) }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}"
delegate_to: localhost

View File

@@ -85,6 +85,7 @@
become_user: "{{ account.become.ansible_user | default('') }}"
become_password: "{{ account.become.ansible_password | default('') }}"
become_private_key_path: "{{ account.become.ansible_ssh_private_key_file | default(None) }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
when: account.secret_type == "password"
delegate_to: localhost
@@ -95,5 +96,6 @@
login_user: "{{ account.username }}"
login_private_key_path: "{{ account.private_key_path }}"
gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
when: account.secret_type == "ssh_key"
delegate_to: localhost

View File

@@ -85,6 +85,7 @@
become_user: "{{ account.become.ansible_user | default('') }}"
become_password: "{{ account.become.ansible_password | default('') }}"
become_private_key_path: "{{ account.become.ansible_ssh_private_key_file | default(None) }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
when: account.secret_type == "password"
delegate_to: localhost
@@ -95,5 +96,6 @@
login_user: "{{ account.username }}"
login_private_key_path: "{{ account.private_key_path }}"
gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
when: account.secret_type == "ssh_key"
delegate_to: localhost

View File

@@ -7,9 +7,9 @@ from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from xlsxwriter import Workbook
from accounts.const import AutomationTypes, SecretType, SSHKeyStrategy, SecretStrategy
from accounts.models import ChangeSecretRecord
from accounts.notifications import ChangeSecretExecutionTaskMsg
from accounts.const import AutomationTypes, SecretType, SSHKeyStrategy, SecretStrategy, ChangeSecretRecordStatusChoice
from accounts.models import ChangeSecretRecord, BaseAccountQuerySet
from accounts.notifications import ChangeSecretExecutionTaskMsg, ChangeSecretFailedMsg
from accounts.serializers import ChangeSecretRecordBackUpSerializer
from assets.const import HostTypes
from common.utils import get_logger
@@ -27,7 +27,7 @@ class ChangeSecretManager(AccountBasePlaybookManager):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.record_id = self.execution.snapshot.get('record_id')
self.record_map = self.execution.snapshot.get('record_map', {})
self.secret_type = self.execution.snapshot.get('secret_type')
self.secret_strategy = self.execution.snapshot.get(
'secret_strategy', SecretStrategy.custom
@@ -68,10 +68,10 @@ class ChangeSecretManager(AccountBasePlaybookManager):
else:
return self.secret_generator(secret_type).get_secret()
def get_accounts(self, privilege_account):
def get_accounts(self, privilege_account) -> BaseAccountQuerySet | None:
if not privilege_account:
print(f'not privilege account')
return []
print('Not privilege account')
return
asset = privilege_account.asset
accounts = asset.accounts.all()
@@ -97,10 +97,9 @@ class ChangeSecretManager(AccountBasePlaybookManager):
return host
accounts = self.get_accounts(account)
error_msg = _("No pending accounts found")
if not accounts:
print('没有发现待处理的账号: %s 用户ID: %s 类型: %s' % (
asset.name, self.account_ids, self.secret_type
))
print(f'{asset}: {error_msg}')
return []
records = []
@@ -109,6 +108,9 @@ class ChangeSecretManager(AccountBasePlaybookManager):
print(f'Windows {asset} does not support ssh key push')
return inventory_hosts
if asset.type == HostTypes.WINDOWS:
accounts = accounts.filter(secret_type=SecretType.PASSWORD)
host['ssh_params'] = {}
for account in accounts:
h = deepcopy(host)
@@ -123,14 +125,20 @@ class ChangeSecretManager(AccountBasePlaybookManager):
print(f'new_secret is None, account: {account}')
continue
if self.record_id is None:
asset_account_id = f'{asset.id}-{account.id}'
if asset_account_id not in self.record_map:
recorder = ChangeSecretRecord(
asset=asset, account=account, execution=self.execution,
old_secret=account.secret, new_secret=new_secret,
)
records.append(recorder)
else:
recorder = ChangeSecretRecord.objects.get(id=self.record_id)
record_id = self.record_map[asset_account_id]
try:
recorder = ChangeSecretRecord.objects.get(id=record_id)
except ChangeSecretRecord.DoesNotExist:
print(f"Record {record_id} not found")
continue
self.name_recorder_mapper[h['name']] = recorder
@@ -158,25 +166,43 @@ class ChangeSecretManager(AccountBasePlaybookManager):
recorder = self.name_recorder_mapper.get(host)
if not recorder:
return
recorder.status = 'success'
recorder.status = ChangeSecretRecordStatusChoice.success.value
recorder.date_finished = timezone.now()
recorder.save()
account = recorder.account
if not account:
print("Account not found, deleted ?")
return
account.secret = recorder.new_secret
account.date_updated = timezone.now()
account.save(update_fields=['secret', 'date_updated'])
max_retries = 3
retry_count = 0
while retry_count < max_retries:
try:
recorder.save()
account.save(update_fields=['secret', 'version', 'date_updated'])
break
except Exception as e:
retry_count += 1
if retry_count == max_retries:
self.on_host_error(host, str(e), result)
else:
print(f'retry {retry_count} times for {host} recorder save error: {e}')
time.sleep(1)
def on_host_error(self, host, error, result):
recorder = self.name_recorder_mapper.get(host)
if not recorder:
return
recorder.status = 'failed'
recorder.status = ChangeSecretRecordStatusChoice.failed.value
recorder.date_finished = timezone.now()
recorder.error = error
recorder.save()
try:
recorder.save()
except Exception as e:
print(f"\033[31m Save {host} recorder error: {e} \033[0m\n")
def on_runner_failed(self, runner, e):
logger.error("Account error: ", e)
@@ -192,7 +218,7 @@ class ChangeSecretManager(AccountBasePlaybookManager):
def get_summary(recorders):
total, succeed, failed = 0, 0, 0
for recorder in recorders:
if recorder.status == 'success':
if recorder.status == ChangeSecretRecordStatusChoice.success.value:
succeed += 1
else:
failed += 1
@@ -203,24 +229,44 @@ class ChangeSecretManager(AccountBasePlaybookManager):
def run(self, *args, **kwargs):
if self.secret_type and not self.check_secret():
self.execution.status = 'success'
self.execution.date_finished = timezone.now()
self.execution.save()
return
super().run(*args, **kwargs)
recorders = list(self.name_recorder_mapper.values())
summary = self.get_summary(recorders)
print(summary, end='')
if self.record_id:
if self.record_map:
return
self.send_recorder_mail(recorders, summary)
failed_recorders = [
r for r in recorders
if r.status == ChangeSecretRecordStatusChoice.failed.value
]
def send_recorder_mail(self, recorders, summary):
recipients = self.execution.recipients
if not recorders or not recipients:
recipients = User.objects.filter(id__in=list(recipients.keys()))
if not recipients:
return
recipients = User.objects.filter(id__in=list(recipients.keys()))
if failed_recorders:
name = self.execution.snapshot.get('name')
execution_id = str(self.execution.id)
_ids = [r.id for r in failed_recorders]
asset_account_errors = ChangeSecretRecord.objects.filter(
id__in=_ids).values_list('asset__name', 'account__username', 'error')
for user in recipients:
ChangeSecretFailedMsg(name, execution_id, user, asset_account_errors).publish()
if not recorders:
return
self.send_recorder_mail(recipients, recorders, summary)
def send_recorder_mail(self, recipients, recorders, summary):
name = self.execution.snapshot['name']
path = os.path.join(os.path.dirname(settings.BASE_DIR), 'tmp')
filename = os.path.join(path, f'{name}-{local_now_filename()}-{time.time()}.xlsx')

View File

@@ -51,14 +51,22 @@ class GatherAccountsManager(AccountBasePlaybookManager):
data = self.generate_data(asset, result)
self.asset_account_info[asset] = data
@staticmethod
def get_nested_info(data, *keys):
for key in keys:
data = data.get(key, {})
if not data:
break
return data
def on_host_success(self, host, result):
info = result.get('debug', {}).get('res', {}).get('info', {})
info = self.get_nested_info(result, 'debug', 'res', 'info')
asset = self.host_asset_mapper.get(host)
if asset and info:
result = self.filter_success_result(asset.type, info)
self.collect_asset_account_info(asset, result)
else:
logger.error(f'Not found {host} info')
print(f'\033[31m Not found {host} info \033[0m\n')
def update_or_create_accounts(self):
for asset, data in self.asset_account_info.items():

View File

@@ -85,6 +85,7 @@
become_user: "{{ account.become.ansible_user | default('') }}"
become_password: "{{ account.become.ansible_password | default('') }}"
become_private_key_path: "{{ account.become.ansible_ssh_private_key_file | default(None) }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
when: account.secret_type == "password"
delegate_to: localhost
@@ -95,6 +96,7 @@
login_user: "{{ account.username }}"
login_private_key_path: "{{ account.private_key_path }}"
gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
when: account.secret_type == "ssh_key"
delegate_to: localhost

View File

@@ -85,6 +85,7 @@
become_user: "{{ account.become.ansible_user | default('') }}"
become_password: "{{ account.become.ansible_password | default('') }}"
become_private_key_path: "{{ account.become.ansible_ssh_private_key_file | default(None) }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
when: account.secret_type == "password"
delegate_to: localhost
@@ -95,6 +96,7 @@
login_user: "{{ account.username }}"
login_private_key_path: "{{ account.private_key_path }}"
gateway_args: "{{ jms_asset.ansible_ssh_common_args | default('') }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
when: account.secret_type == "ssh_key"
delegate_to: localhost

View File

@@ -2,6 +2,7 @@
gather_facts: no
vars:
ansible_python_interpreter: /opt/py3/bin/python
check_ssl: "{{ jms_asset.spec_info.use_ssl and not jms_asset.spec_info.allow_invalid_cert }}"
tasks:
- name: "Remove account"

View File

@@ -12,11 +12,13 @@
path: "{{ user_home_dir.stdout }}"
register: home_dir
when: user_home_dir.stdout != ""
ignore_errors: yes
- name: "Rename user home directory if it exists"
ansible.builtin.command:
cmd: "mv {{ user_home_dir.stdout }} {{ user_home_dir.stdout }}.bak"
when: home_dir.stat | default(false) and user_home_dir.stdout != ""
ignore_errors: yes
- name: "Remove account"
ansible.builtin.user:

View File

@@ -4,6 +4,4 @@
- name: "Remove account"
ansible.windows.win_user:
name: "{{ account.username }}"
state: absent
purge: yes
force: yes
state: absent

View File

@@ -60,8 +60,11 @@ class RemoveAccountManager(AccountBasePlaybookManager):
if not tuple_asset_gather_account:
return
asset, gather_account = tuple_asset_gather_account
Account.objects.filter(
asset_id=asset.id,
username=gather_account.username
).delete()
gather_account.delete()
try:
Account.objects.filter(
asset_id=asset.id,
username=gather_account.username
).delete()
gather_account.delete()
except Exception as e:
print(f'\033[31m Delete account {gather_account.username} failed: {e} \033[0m\n')

View File

@@ -3,6 +3,7 @@
vars:
ansible_shell_type: sh
ansible_connection: local
ansible_python_interpreter: /opt/py3/bin/python
tasks:
- name: Verify account (pyfreerdp)

View File

@@ -19,3 +19,5 @@
become_user: "{{ account.become.ansible_user | default('') }}"
become_password: "{{ account.become.ansible_password | default('') }}"
become_private_key_path: "{{ account.become.ansible_ssh_private_key_file | default(None) }}"
old_ssh_version: "{{ jms_asset.old_ssh_version | default(False) }}"
gateway_args: "{{ jms_asset.ansible_ssh_common_args | default(None) }}"

View File

@@ -76,8 +76,14 @@ class VerifyAccountManager(AccountBasePlaybookManager):
def on_host_success(self, host, result):
account = self.host_account_mapper.get(host)
account.set_connectivity(Connectivity.OK)
try:
account.set_connectivity(Connectivity.OK)
except Exception as e:
print(f'\033[31m Update account {account.name} connectivity failed: {e} \033[0m\n')
def on_host_error(self, host, error, result):
account = self.host_account_mapper.get(host)
account.set_connectivity(Connectivity.ERR)
try:
account.set_connectivity(Connectivity.ERR)
except Exception as e:
print(f'\033[31m Update account {account.name} connectivity failed: {e} \033[0m\n')

View File

@@ -15,6 +15,7 @@ class AliasAccount(TextChoices):
INPUT = '@INPUT', _('Manual input')
USER = '@USER', _('Dynamic user')
ANON = '@ANON', _('Anonymous account')
SPEC = '@SPEC', _('Specified account')
@classmethod
def virtual_choices(cls):

View File

@@ -16,7 +16,7 @@ DEFAULT_PASSWORD_RULES = {
__all__ = [
'AutomationTypes', 'SecretStrategy', 'SSHKeyStrategy', 'Connectivity',
'DEFAULT_PASSWORD_LENGTH', 'DEFAULT_PASSWORD_RULES', 'TriggerChoice',
'PushAccountActionChoice', 'AccountBackupType'
'PushAccountActionChoice', 'AccountBackupType', 'ChangeSecretRecordStatusChoice',
]
@@ -103,3 +103,9 @@ class AccountBackupType(models.TextChoices):
email = 'email', _('Email')
# 目前只支持sftp方式
object_storage = 'object_storage', _('SFTP')
class ChangeSecretRecordStatusChoice(models.TextChoices):
failed = 'failed', _('Failed')
success = 'success', _('Success')
pending = 'pending', _('Pending')

View File

@@ -5,7 +5,7 @@ from django_filters import rest_framework as drf_filters
from assets.models import Node
from common.drf.filters import BaseFilterSet
from .models import Account, GatheredAccount
from .models import Account, GatheredAccount, ChangeSecretRecord
class AccountFilterSet(BaseFilterSet):
@@ -61,3 +61,13 @@ class GatheredAccountFilterSet(BaseFilterSet):
class Meta:
model = GatheredAccount
fields = ['id', 'username']
class ChangeSecretRecordFilterSet(BaseFilterSet):
asset_name = drf_filters.CharFilter(field_name='asset__name', lookup_expr='icontains')
account_username = drf_filters.CharFilter(field_name='account__username', lookup_expr='icontains')
execution_id = drf_filters.CharFilter(field_name='execution_id', lookup_expr='exact')
class Meta:
model = ChangeSecretRecord
fields = ['id', 'status', 'asset_id', 'execution']

View File

@@ -1,10 +1,8 @@
# Generated by Django 3.2.14 on 2022-12-28 07:29
# Generated by Django 4.1.13 on 2024-05-09 03:16
import uuid
import django.db.models.deletion
import simple_history.models
from django.conf import settings
from django.db import migrations, models
import common.db.encoder
@@ -12,11 +10,10 @@ import common.db.fields
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('assets', '0098_auto_20220430_2126'),
]
operations = [
@@ -29,63 +26,65 @@ class Migration(migrations.Migration):
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('connectivity',
models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-',
max_length=16, verbose_name='Connectivity')),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('connectivity', models.CharField(choices=[('-', 'Unknown'), ('ok', 'OK'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')),
('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')),
('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')),
('secret_type', models.CharField(
choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'),
('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16,
verbose_name='Secret type')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')),
('privileged', models.BooleanField(default=False, verbose_name='Privileged')),
('is_active', models.BooleanField(default=True, verbose_name='Is active')),
('version', models.IntegerField(default=0, verbose_name='Version')),
('source', models.CharField(default='local', max_length=30, verbose_name='Source')),
('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts',
to='assets.asset', verbose_name='Asset')),
('su_from',
models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to',
to='accounts.account', verbose_name='Su from')),
('source_id', models.CharField(blank=True, max_length=128, null=True, verbose_name='Source ID')),
],
options={
'verbose_name': 'Account',
'permissions': [('view_accountsecret', 'Can view asset account secret'),
('view_historyaccount', 'Can view asset history account'),
('view_historyaccountsecret', 'Can view asset history account secret')],
'unique_together': {('username', 'asset', 'secret_type'), ('name', 'asset')},
'permissions': [('view_accountsecret', 'Can view asset account secret'), ('view_historyaccount', 'Can view asset history account'), ('view_historyaccountsecret', 'Can view asset history account secret'), ('verify_account', 'Can verify account'), ('push_account', 'Can push account'), ('remove_account', 'Can remove account')],
},
),
migrations.CreateModel(
name='HistoricalAccount',
name='AccountBackupAutomation',
fields=[
('id', models.UUIDField(db_index=True, default=uuid.uuid4)),
('secret_type', models.CharField(
choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'),
('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16,
verbose_name='Secret type')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('version', models.IntegerField(default=0, verbose_name='Version')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type',
models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user',
models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+',
to=settings.AUTH_USER_MODEL)),
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')),
('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')),
('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')),
('types', models.JSONField(default=list)),
('backup_type', models.CharField(choices=[('email', 'Email'), ('object_storage', 'SFTP')], default='email', max_length=128, verbose_name='Backup type')),
('is_password_divided_by_email', models.BooleanField(default=True, verbose_name='Password divided')),
('is_password_divided_by_obj_storage', models.BooleanField(default=True, verbose_name='Password divided')),
('zip_encrypt_password', common.db.fields.EncryptCharField(blank=True, max_length=4096, null=True, verbose_name='Zip encrypt password')),
],
options={
'verbose_name': 'historical Account',
'verbose_name_plural': 'historical Accounts',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
'verbose_name': 'Account backup plan',
'ordering': ['name'],
},
),
migrations.CreateModel(
name='AccountBackupExecution',
fields=[
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Date start')),
('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')),
('snapshot', models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, verbose_name='Account backup snapshot')),
('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')),
('reason', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Reason')),
('is_success', models.BooleanField(default=False, verbose_name='Is success')),
],
options={
'verbose_name': 'Account backup execution',
'ordering': ('-date_start',),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='AccountTemplate',
@@ -96,23 +95,96 @@ class Migration(migrations.Migration):
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')),
('password_rules', models.JSONField(default=dict, verbose_name='Password rules')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')),
('secret_type', models.CharField(
choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'),
('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16,
verbose_name='Secret type')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')),
('privileged', models.BooleanField(default=False, verbose_name='Privileged')),
('is_active', models.BooleanField(default=True, verbose_name='Is active')),
('auto_push', models.BooleanField(default=False, verbose_name='Auto push')),
('push_params', models.JSONField(default=dict, verbose_name='Push params')),
],
options={
'verbose_name': 'Account template',
'permissions': [('view_accounttemplatesecret', 'Can view asset account template secret'),
('change_accounttemplatesecret', 'Can change asset account template secret')],
'unique_together': {('name', 'org_id')},
'permissions': [('view_accounttemplatesecret', 'Can view asset account template secret')],
},
),
migrations.CreateModel(
name='ChangeSecretRecord',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('old_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Old secret')),
('new_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='New secret')),
('date_started', models.DateTimeField(blank=True, null=True, verbose_name='Date started')),
('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='Date finished')),
('status', models.CharField(default='pending', max_length=16, verbose_name='Status')),
('error', models.TextField(blank=True, null=True, verbose_name='Error')),
],
options={
'verbose_name': 'Change secret record',
'ordering': ('-date_created',),
},
),
migrations.CreateModel(
name='GatheredAccount',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('present', models.BooleanField(default=True, verbose_name='Present')),
('date_last_login', models.DateTimeField(null=True, verbose_name='Date login')),
('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')),
('address_last_login', models.CharField(default='', max_length=39, verbose_name='Address login')),
],
options={
'verbose_name': 'Gather asset accounts',
'ordering': ['asset'],
},
),
migrations.CreateModel(
name='HistoricalAccount',
fields=[
('id', models.UUIDField(db_index=True, default=uuid.uuid4)),
('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')),
('version', models.IntegerField(default=0, verbose_name='Version')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
],
options={
'verbose_name': 'historical Account',
'verbose_name_plural': 'historical Accounts',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='VirtualAccount',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('alias', models.CharField(choices=[('@INPUT', 'Manual input'), ('@USER', 'Dynamic user'), ('@ANON', 'Anonymous account'), ('@SPEC', 'Specified account')], max_length=128, verbose_name='Alias')),
('secret_from_login', models.BooleanField(default=None, null=True, verbose_name='Secret from login')),
],
options={'verbose_name': 'Virtual account'},
),
]

View File

@@ -1,44 +1,103 @@
# Generated by Django 3.2.14 on 2022-12-28 10:39
# Generated by Django 4.1.13 on 2024-05-09 03:16
import common.db.encoder
import common.db.fields
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
from django.db import migrations, models
import common.db.fields
class Migration(migrations.Migration):
initial = True
dependencies = [
('assets', '0106_auto_20221228_1838'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('assets', '0001_initial'),
('accounts', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='AccountBackupAutomation',
name='AccountBaseAutomation',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('is_periodic', models.BooleanField(default=False, verbose_name='Periodic perform')),
('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform')),
('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform')),
('types', models.JSONField(default=list)),
('recipients', models.ManyToManyField(blank=True, related_name='recipient_escape_route_plans',
to=settings.AUTH_USER_MODEL, verbose_name='Recipient')),
],
options={
'verbose_name': 'Account backup plan',
'ordering': ['name'],
'unique_together': {('name', 'org_id')},
'verbose_name': 'Account automation task',
'proxy': True,
'indexes': [],
'constraints': [],
},
)
bases=('assets.baseautomation',),
),
migrations.CreateModel(
name='AutomationExecution',
fields=[
],
options={
'verbose_name': 'Automation execution',
'verbose_name_plural': 'Automation executions',
'permissions': [('view_changesecretexecution', 'Can view change secret execution'), ('add_changesecretexecution', 'Can add change secret execution'), ('view_gatheraccountsexecution', 'Can view gather accounts execution'), ('add_gatheraccountsexecution', 'Can add gather accounts execution'), ('view_pushaccountexecution', 'Can view push account execution'), ('add_pushaccountexecution', 'Can add push account execution')],
'proxy': True,
'indexes': [],
'constraints': [],
},
bases=('assets.automationexecution',),
),
migrations.CreateModel(
name='ChangeSecretAutomation',
fields=[
('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')),
('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')),
('password_rules', models.JSONField(default=dict, verbose_name='Password rules')),
('ssh_key_change_strategy', models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy')),
],
options={
'verbose_name': 'Change secret automation',
},
bases=('accounts.accountbaseautomation', models.Model),
),
migrations.CreateModel(
name='GatherAccountsAutomation',
fields=[
('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')),
('is_sync_account', models.BooleanField(blank=True, default=False, verbose_name='Is sync account')),
],
options={
'verbose_name': 'Gather account automation',
},
bases=('accounts.accountbaseautomation',),
),
migrations.CreateModel(
name='PushAccountAutomation',
fields=[
('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')),
('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')),
('password_rules', models.JSONField(default=dict, verbose_name='Password rules')),
('ssh_key_change_strategy', models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy')),
('triggers', models.JSONField(default=list, max_length=16, verbose_name='Triggers')),
('username', models.CharField(max_length=128, verbose_name='Username')),
('action', models.CharField(max_length=16, verbose_name='Action')),
],
options={
'verbose_name': 'Push asset account',
},
bases=('accounts.accountbaseautomation', models.Model),
),
migrations.CreateModel(
name='VerifyAccountAutomation',
fields=[
('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')),
],
options={
'verbose_name': 'Verify asset account',
},
bases=('accounts.accountbaseautomation',),
),
migrations.AlterUniqueTogether(
name='virtualaccount',
unique_together={('alias', 'org_id')},
),
]

View File

@@ -1,198 +1,116 @@
# Generated by Django 3.2.16 on 2022-12-30 08:08
# Generated by Django 4.1.13 on 2024-05-09 03:16
import uuid
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import common.db.encoder
import common.db.fields
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('assets', '0107_automation'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('assets', '0001_initial'),
('terminal', '0001_initial'),
('accounts', '0002_auto_20220616_0021'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='AccountBaseAutomation',
fields=[
],
options={
'verbose_name': 'Account automation task',
'proxy': True,
'indexes': [],
'constraints': [],
},
bases=('assets.baseautomation',),
migrations.AddField(
model_name='historicalaccount',
name='history_user',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.CreateModel(
name='AutomationExecution',
fields=[
],
options={
'verbose_name': 'Automation execution',
'verbose_name_plural': 'Automation executions',
'permissions': [('view_changesecretexecution', 'Can view change secret execution'),
('add_changesecretexecution', 'Can add change secret execution'),
('view_gatheraccountsexecution', 'Can view gather accounts execution'),
('add_gatheraccountsexecution', 'Can add gather accounts execution')],
'proxy': True,
'indexes': [],
'constraints': [],
},
bases=('assets.automationexecution',),
migrations.AddField(
model_name='gatheredaccount',
name='asset',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.asset', verbose_name='Asset'),
),
migrations.CreateModel(
name='PushAccountAutomation',
fields=[
('baseautomation_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.baseautomation')),
('secret_type', models.CharField(
choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'),
('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16,
verbose_name='Secret type')),
('secret_strategy', models.CharField(choices=[('specific', 'Specific password'),
('random_one', 'All assets use the same random password'),
('random_all',
'All assets use different random password')],
default='specific', max_length=16,
verbose_name='Secret strategy')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('password_rules', models.JSONField(default=dict, verbose_name='Password rules')),
('ssh_key_change_strategy', models.CharField(
choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'),
('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16,
verbose_name='SSH key change strategy')),
('triggers', models.JSONField(default=list, max_length=16, verbose_name='Triggers')),
('username', models.CharField(max_length=128, verbose_name='Username')),
('action', models.CharField(max_length=16, verbose_name='Action')),
],
options={
'verbose_name': 'Push asset account',
},
bases=('accounts.accountbaseautomation', models.Model),
migrations.AddField(
model_name='changesecretrecord',
name='account',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='accounts.account'),
),
migrations.CreateModel(
name='GatherAccountsAutomation',
fields=[
('baseautomation_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.baseautomation')),
],
options={
'verbose_name': 'Gather asset accounts',
},
bases=('accounts.accountbaseautomation',),
migrations.AddField(
model_name='changesecretrecord',
name='asset',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.asset'),
),
migrations.CreateModel(
name='VerifyAccountAutomation',
fields=[
('baseautomation_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.baseautomation')),
],
options={
'verbose_name': 'Verify asset account',
},
bases=('accounts.accountbaseautomation',),
migrations.AddField(
model_name='changesecretrecord',
name='execution',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounts.automationexecution'),
),
migrations.CreateModel(
name='ChangeSecretRecord',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('old_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Old secret')),
('new_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='New secret')),
('date_started', models.DateTimeField(blank=True, null=True, verbose_name='Date started')),
('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='Date finished')),
('status', models.CharField(default='pending', max_length=16, verbose_name='Status')),
('error', models.TextField(blank=True, null=True, verbose_name='Error')),
('account',
models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='accounts.account')),
('asset', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.asset')),
('execution',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounts.automationexecution')),
],
options={
'verbose_name': 'Change secret record',
},
migrations.AddField(
model_name='accounttemplate',
name='platforms',
field=models.ManyToManyField(blank=True, related_name='account_templates', to='assets.platform', verbose_name='Platforms'),
),
migrations.CreateModel(
name='AccountBackupExecution',
fields=[
('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Date start')),
('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')),
('plan_snapshot',
models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True,
verbose_name='Account backup snapshot')),
('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')],
default='manual', max_length=128, verbose_name='Trigger mode')),
('reason', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Reason')),
('is_success', models.BooleanField(default=False, verbose_name='Is success')),
('plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='execution',
to='accounts.accountbackupautomation', verbose_name='Account backup plan')),
],
options={
'verbose_name': 'Account backup execution',
'ordering': ('-date_start',),
},
migrations.AddField(
model_name='accounttemplate',
name='su_from',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.accounttemplate', verbose_name='Su from'),
),
migrations.CreateModel(
name='ChangeSecretAutomation',
fields=[
('baseautomation_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='assets.baseautomation')),
('secret_type', models.CharField(
choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'),
('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16,
verbose_name='Secret type')),
('secret_strategy', models.CharField(choices=[('specific', 'Specific password'),
('random_one', 'All assets use the same random password'),
('random_all',
'All assets use different random password')],
default='specific', max_length=16,
verbose_name='Secret strategy')),
('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('password_rules', models.JSONField(default=dict, verbose_name='Password rules')),
('ssh_key_change_strategy', models.CharField(
choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'),
('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16,
verbose_name='SSH key change strategy')),
('recipients',
models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient')),
],
options={
'verbose_name': 'Change secret automation',
},
bases=('accounts.accountbaseautomation', models.Model),
migrations.AddField(
model_name='accountbackupexecution',
name='plan',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='execution', to='accounts.accountbackupautomation', verbose_name='Account backup plan'),
),
migrations.AlterModelOptions(
name='automationexecution',
options={'permissions': [('view_changesecretexecution', 'Can view change secret execution'),
('add_changesecretexecution', 'Can add change secret execution'),
('view_gatheraccountsexecution', 'Can view gather accounts execution'),
('add_gatheraccountsexecution', 'Can add gather accounts execution'),
('view_pushaccountexecution', 'Can view push account execution'),
('add_pushaccountexecution', 'Can add push account execution')],
'verbose_name': 'Automation execution', 'verbose_name_plural': 'Automation executions'},
migrations.AddField(
model_name='accountbackupautomation',
name='obj_recipients_part_one',
field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_one_plans', to='terminal.replaystorage', verbose_name='Object storage recipient part one'),
),
migrations.AlterModelOptions(
name='changesecretrecord',
options={'ordering': ('-date_started',), 'verbose_name': 'Change secret record'},
migrations.AddField(
model_name='accountbackupautomation',
name='obj_recipients_part_two',
field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_two_plans', to='terminal.replaystorage', verbose_name='Object storage recipient part two'),
),
migrations.AddField(
model_name='accountbackupautomation',
name='recipients_part_one',
field=models.ManyToManyField(blank=True, related_name='recipient_part_one_plans', to=settings.AUTH_USER_MODEL, verbose_name='Recipient part one'),
),
migrations.AddField(
model_name='accountbackupautomation',
name='recipients_part_two',
field=models.ManyToManyField(blank=True, related_name='recipient_part_two_plans', to=settings.AUTH_USER_MODEL, verbose_name='Recipient part two'),
),
migrations.AddField(
model_name='account',
name='asset',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to='assets.asset', verbose_name='Asset'),
),
migrations.AddField(
model_name='account',
name='su_from',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.account', verbose_name='Su from'),
),
migrations.AlterUniqueTogether(
name='gatheredaccount',
unique_together={('username', 'asset')},
),
migrations.AddField(
model_name='gatheraccountsautomation',
name='recipients',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient'),
),
migrations.AddField(
model_name='changesecretautomation',
name='recipients',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient'),
),
migrations.AlterUniqueTogether(
name='accounttemplate',
unique_together={('name', 'org_id')},
),
migrations.AlterUniqueTogether(
name='accountbackupautomation',
unique_together={('name', 'org_id')},
),
migrations.AlterUniqueTogether(
name='account',
unique_together={('name', 'asset'), ('username', 'asset', 'secret_type')},
),
]

View File

@@ -1,23 +0,0 @@
# Generated by Django 3.2.16 on 2023-01-06 07:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0003_automation'),
]
operations = [
migrations.AlterField(
model_name='changesecretautomation',
name='secret_strategy',
field=models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy'),
),
migrations.AlterField(
model_name='pushaccountautomation',
name='secret_strategy',
field=models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy'),
),
]

View File

@@ -1,17 +0,0 @@
# Generated by Django 3.2.16 on 2023-01-10 06:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0004_auto_20230106_1507'),
]
operations = [
migrations.AlterModelOptions(
name='changesecretrecord',
options={'ordering': ('-date_created',), 'verbose_name': 'Change secret record'},
),
]

View File

@@ -1,38 +0,0 @@
# Generated by Django 3.2.16 on 2023-02-07 04:41
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('assets', '0108_alter_platform_charset'),
('accounts', '0005_alter_changesecretrecord_options'),
]
operations = [
migrations.CreateModel(
name='GatheredAccount',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('present', models.BooleanField(default=True, verbose_name='Present')),
('date_last_login', models.DateTimeField(null=True, verbose_name='Date last login')),
('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')),
('address_last_login', models.CharField(default='', max_length=39, verbose_name='Address last login')),
('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.asset', verbose_name='Asset')),
],
options={
'verbose_name': 'Gather account',
'ordering': ['asset'],
'unique_together': {('username', 'asset')},
},
),
]

View File

@@ -1,23 +0,0 @@
# Generated by Django 3.2.16 on 2023-02-16 11:07
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0006_gatheredaccount'),
]
operations = [
migrations.AlterModelOptions(
name='account',
options={'permissions': [
('view_accountsecret', 'Can view asset account secret'),
('view_historyaccount', 'Can view asset history account'),
('view_historyaccountsecret', 'Can view asset history account secret'),
('verify_account', 'Can verify account'),
('push_account', 'Can push account'),
('remove_account', 'Can remove account'),
], 'verbose_name': 'Account'},
),
]

View File

@@ -1,17 +0,0 @@
# Generated by Django 3.2.16 on 2023-02-23 09:59
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0007_alter_account_options'),
]
operations = [
migrations.AlterModelOptions(
name='gatheredaccount',
options={'ordering': ['asset'], 'verbose_name': 'Gather account automation'},
),
]

View File

@@ -1,69 +0,0 @@
# Generated by Django 3.2.16 on 2023-03-07 07:36
from django.db import migrations
from django.db.models import Q
def get_nodes_all_assets(apps, *nodes):
node_model = apps.get_model('assets', 'Node')
asset_model = apps.get_model('assets', 'Asset')
node_ids = set()
descendant_node_query = Q()
for n in nodes:
node_ids.add(n.id)
descendant_node_query |= Q(key__istartswith=f'{n.key}:')
if descendant_node_query:
_ids = node_model.objects.order_by().filter(descendant_node_query).values_list('id', flat=True)
node_ids.update(_ids)
return asset_model.objects.order_by().filter(nodes__id__in=node_ids).distinct()
def get_all_assets(apps, snapshot):
node_model = apps.get_model('assets', 'Node')
asset_model = apps.get_model('assets', 'Asset')
asset_ids = snapshot.get('assets', [])
node_ids = snapshot.get('nodes', [])
nodes = node_model.objects.filter(id__in=node_ids)
node_asset_ids = get_nodes_all_assets(apps, *nodes).values_list('id', flat=True)
asset_ids = set(list(asset_ids) + list(node_asset_ids))
return asset_model.objects.filter(id__in=asset_ids)
def migrate_account_usernames_to_ids(apps, schema_editor):
db_alias = schema_editor.connection.alias
execution_model = apps.get_model('accounts', 'AutomationExecution')
account_model = apps.get_model('accounts', 'Account')
executions = execution_model.objects.using(db_alias).all()
executions_update = []
for execution in executions:
snapshot = execution.snapshot
accounts = account_model.objects.none()
account_usernames = snapshot.get('accounts', [])
for asset in get_all_assets(apps, snapshot):
accounts = accounts | asset.accounts.all()
secret_type = snapshot.get('secret_type')
if secret_type:
ids = accounts.filter(
username__in=account_usernames,
secret_type=secret_type
).values_list('id', flat=True)
else:
ids = accounts.filter(
username__in=account_usernames
).values_list('id', flat=True)
snapshot['accounts'] = [str(_id) for _id in ids]
execution.snapshot = snapshot
executions_update.append(execution)
execution_model.objects.bulk_update(executions_update, ['snapshot'])
class Migration(migrations.Migration):
dependencies = [
('accounts', '0008_alter_gatheredaccount_options'),
]
operations = [
migrations.RunPython(migrate_account_usernames_to_ids),
]

View File

@@ -1,22 +0,0 @@
# Generated by Django 3.2.16 on 2023-03-23 08:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0009_account_usernames_to_ids'),
]
operations = [
migrations.AddField(
model_name='gatheraccountsautomation',
name='is_sync_account',
field=models.BooleanField(blank=True, default=False, verbose_name='Is sync account'),
),
migrations.AddField(
model_name='account',
name='source_id',
field=models.CharField(max_length=128, null=True, blank=True, verbose_name='Source ID'),
),
]

View File

@@ -1,29 +0,0 @@
# Generated by Django 3.2.17 on 2023-05-06 06:43
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('accounts', '0010_gatheraccountsautomation_is_sync_account'),
]
operations = [
migrations.AddField(
model_name='accounttemplate',
name='su_from',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.accounttemplate', verbose_name='Su from'),
),
migrations.AlterField(
model_name='changesecretautomation',
name='ssh_key_change_strategy',
field=models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy'),
),
migrations.AlterField(
model_name='pushaccountautomation',
name='ssh_key_change_strategy',
field=models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy'),
),
]

View File

@@ -1,28 +0,0 @@
# Generated by Django 3.2.19 on 2023-06-21 06:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0011_auto_20230506_1443'),
]
operations = [
migrations.RenameField(
model_name='account',
old_name='secret',
new_name='_secret',
),
migrations.RenameField(
model_name='accounttemplate',
old_name='secret',
new_name='_secret',
),
migrations.RenameField(
model_name='historicalaccount',
old_name='secret',
new_name='_secret',
),
]

View File

@@ -1,77 +0,0 @@
# Generated by Django 4.1.10 on 2023-08-03 08:28
from django.conf import settings
from django.db import migrations, models
import common.db.encoder
def migrate_recipients(apps, schema_editor):
account_backup_model = apps.get_model('accounts', 'AccountBackupAutomation')
execution_model = apps.get_model('accounts', 'AccountBackupExecution')
for account_backup in account_backup_model.objects.all():
recipients = list(account_backup.recipients.all())
if not recipients:
continue
account_backup.recipients_part_one.set(recipients)
objs = []
for execution in execution_model.objects.all():
snapshot = execution.snapshot
recipients = snapshot.pop('recipients', {})
snapshot.update({'recipients_part_one': recipients, 'recipients_part_two': {}})
objs.append(execution)
execution_model.objects.bulk_update(objs, ['snapshot'])
def migrate_snapshot(apps, schema_editor):
model = apps.get_model('accounts', 'AccountBackupExecution')
objs = []
for execution in model.objects.all():
execution.snapshot = execution.plan_snapshot
objs.append(execution)
model.objects.bulk_update(objs, ['snapshot'])
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('accounts', '0012_auto_20230621_1456'),
]
operations = [
migrations.AddField(
model_name='accountbackupautomation',
name='recipients_part_one',
field=models.ManyToManyField(
blank=True, related_name='recipient_part_one_plans',
to=settings.AUTH_USER_MODEL, verbose_name='Recipient part one'
),
),
migrations.AddField(
model_name='accountbackupautomation',
name='recipients_part_two',
field=models.ManyToManyField(
blank=True, related_name='recipient_part_two_plans',
to=settings.AUTH_USER_MODEL, verbose_name='Recipient part two'
),
),
migrations.AddField(
model_name='accountbackupexecution',
name='snapshot',
field=models.JSONField(
default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder,
null=True, blank=True, verbose_name='Account backup snapshot'
),
),
migrations.RunPython(migrate_snapshot),
migrations.RunPython(migrate_recipients),
migrations.RemoveField(
model_name='accountbackupexecution',
name='plan_snapshot',
),
migrations.RemoveField(
model_name='accountbackupautomation',
name='recipients',
),
]

View File

@@ -1,30 +0,0 @@
# Generated by Django 4.1.10 on 2023-08-01 09:12
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('accounts', '0013_account_backup_recipients'),
]
operations = [
migrations.CreateModel(
name='VirtualAccount',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('alias', models.CharField(choices=[('@INPUT', 'Manual input'), ('@USER', 'Dynamic user'), ('@ANON', 'Anonymous account')], max_length=128, verbose_name='Alias')),
('secret_from_login', models.BooleanField(default=None, null=True, verbose_name='Secret from login')),
],
options={
'unique_together': {('alias', 'org_id')},
},
),
]

View File

@@ -1,34 +0,0 @@
# Generated by Django 4.1.10 on 2023-08-25 03:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0122_auto_20230803_1553'),
('accounts', '0014_virtualaccount'),
]
operations = [
migrations.AddField(
model_name='accounttemplate',
name='auto_push',
field=models.BooleanField(default=False, verbose_name='Auto push'),
),
migrations.AddField(
model_name='accounttemplate',
name='platforms',
field=models.ManyToManyField(related_name='account_templates', to='assets.platform', verbose_name='Platforms', blank=True),
),
migrations.AddField(
model_name='accounttemplate',
name='push_params',
field=models.JSONField(default=dict, verbose_name='Push params'),
),
migrations.AddField(
model_name='accounttemplate',
name='secret_strategy',
field=models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy'),
),
]

View File

@@ -1,18 +0,0 @@
# Generated by Django 4.1.10 on 2023-09-18 08:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0015_auto_20230825_1120'),
]
operations = [
migrations.AddField(
model_name='accounttemplate',
name='password_rules',
field=models.JSONField(default=dict, verbose_name='Password rules'),
),
]

View File

@@ -1,25 +0,0 @@
# Generated by Django 4.1.10 on 2023-10-24 05:59
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0016_accounttemplate_password_rules'),
]
operations = [
migrations.AlterModelOptions(
name='automationexecution',
options={
'permissions': [
('view_changesecretexecution', 'Can view change secret execution'),
('add_changesecretexecution', 'Can add change secret execution'),
('view_gatheraccountsexecution', 'Can view gather accounts execution'),
('add_gatheraccountsexecution', 'Can add gather accounts execution'),
('view_pushaccountexecution', 'Can view push account execution'),
('add_pushaccountexecution', 'Can add push account execution')
],
'verbose_name': 'Automation execution', 'verbose_name_plural': 'Automation executions'},
),
]

View File

@@ -1,45 +0,0 @@
# Generated by Django 4.1.10 on 2023-11-03 07:10
import common.db.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('terminal', '0067_alter_replaystorage_type'),
('accounts', '0017_alter_automationexecution_options'),
]
operations = [
migrations.AddField(
model_name='accountbackupautomation',
name='backup_type',
field=models.CharField(choices=[('email', 'Email'), ('object_storage', 'Object Storage')], default='email', max_length=128),
),
migrations.AddField(
model_name='accountbackupautomation',
name='is_password_divided_by_email',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='accountbackupautomation',
name='is_password_divided_by_obj_storage',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='accountbackupautomation',
name='obj_recipients_part_one',
field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_one_plans', to='terminal.replaystorage', verbose_name='Object Storage Recipient part one'),
),
migrations.AddField(
model_name='accountbackupautomation',
name='obj_recipients_part_two',
field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_two_plans', to='terminal.replaystorage', verbose_name='Object Storage Recipient part two'),
),
migrations.AddField(
model_name='accountbackupautomation',
name='zip_encrypt_password',
field=common.db.fields.EncryptCharField(blank=True, max_length=4096, null=True, verbose_name='Zip Encrypt Password'),
),
]

View File

@@ -1,20 +0,0 @@
# Generated by Django 4.1.10 on 2023-10-31 06:12
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('accounts', '0018_accountbackupautomation_backup_type_and_more'),
]
operations = [
migrations.AddField(
model_name='gatheraccountsautomation',
name='recipients',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient'),
),
]

View File

@@ -1,28 +0,0 @@
# Generated by Django 4.1.10 on 2023-11-16 02:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0019_gatheraccountsautomation_recipients'),
]
operations = [
migrations.AlterField(
model_name='accountbackupautomation',
name='backup_type',
field=models.CharField(choices=[('email', 'Email'), ('object_storage', 'SFTP')], default='email', max_length=128, verbose_name='Backup Type'),
),
migrations.AlterField(
model_name='accountbackupautomation',
name='is_password_divided_by_email',
field=models.BooleanField(default=True, verbose_name='Is Password Divided'),
),
migrations.AlterField(
model_name='accountbackupautomation',
name='is_password_divided_by_obj_storage',
field=models.BooleanField(default=True, verbose_name='Is Password Divided'),
),
]

View File

@@ -8,7 +8,7 @@ from django.db import models
from django.db.models import F
from django.utils.translation import gettext_lazy as _
from accounts.const.automation import AccountBackupType
from accounts.const import AccountBackupType
from common.const.choices import Trigger
from common.db import fields
from common.db.encoder import ModelJSONFieldEncoder
@@ -24,9 +24,9 @@ logger = get_logger(__file__)
class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
types = models.JSONField(default=list)
backup_type = models.CharField(max_length=128, choices=AccountBackupType.choices,
default=AccountBackupType.email.value, verbose_name=_('Backup Type'))
is_password_divided_by_email = models.BooleanField(default=True, verbose_name=_('Is Password Divided'))
is_password_divided_by_obj_storage = models.BooleanField(default=True, verbose_name=_('Is Password Divided'))
default=AccountBackupType.email.value, verbose_name=_('Backup type'))
is_password_divided_by_email = models.BooleanField(default=True, verbose_name=_('Password divided'))
is_password_divided_by_obj_storage = models.BooleanField(default=True, verbose_name=_('Password divided'))
recipients_part_one = models.ManyToManyField(
'users.User', related_name='recipient_part_one_plans', blank=True,
verbose_name=_("Recipient part one")
@@ -37,14 +37,15 @@ class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
)
obj_recipients_part_one = models.ManyToManyField(
'terminal.ReplayStorage', related_name='obj_recipient_part_one_plans', blank=True,
verbose_name=_("Object Storage Recipient part one")
verbose_name=_("Object storage recipient part one")
)
obj_recipients_part_two = models.ManyToManyField(
'terminal.ReplayStorage', related_name='obj_recipient_part_two_plans', blank=True,
verbose_name=_("Object Storage Recipient part two")
verbose_name=_("Object storage recipient part two")
)
zip_encrypt_password = fields.EncryptCharField(
max_length=4096, blank=True, null=True, verbose_name=_('Zip encrypt password')
)
zip_encrypt_password = fields.EncryptCharField(max_length=4096, blank=True, null=True,
verbose_name=_('Zip Encrypt Password'))
def __str__(self):
return f'{self.name}({self.org_id})'

View File

@@ -2,7 +2,7 @@ from django.db import models
from django.utils.translation import gettext_lazy as _
from accounts.const import (
AutomationTypes
AutomationTypes, ChangeSecretRecordStatusChoice
)
from common.db import fields
from common.db.models import JMSBaseModel
@@ -40,7 +40,10 @@ class ChangeSecretRecord(JMSBaseModel):
new_secret = fields.EncryptTextField(blank=True, null=True, verbose_name=_('New secret'))
date_started = models.DateTimeField(blank=True, null=True, verbose_name=_('Date started'))
date_finished = models.DateTimeField(blank=True, null=True, verbose_name=_('Date finished'))
status = models.CharField(max_length=16, default='pending', verbose_name=_('Status'))
status = models.CharField(
max_length=16, verbose_name=_('Status'),
default=ChangeSecretRecordStatusChoice.pending.value
)
error = models.TextField(blank=True, null=True, verbose_name=_('Error'))
class Meta:

View File

@@ -12,10 +12,10 @@ __all__ = ['GatherAccountsAutomation', 'GatheredAccount']
class GatheredAccount(JMSOrgBaseModel):
present = models.BooleanField(default=True, verbose_name=_("Present"))
date_last_login = models.DateTimeField(null=True, verbose_name=_("Date last login"))
date_last_login = models.DateTimeField(null=True, verbose_name=_("Date login"))
asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE, verbose_name=_("Asset"))
username = models.CharField(max_length=32, blank=True, db_index=True, verbose_name=_('Username'))
address_last_login = models.CharField(max_length=39, default='', verbose_name=_("Address last login"))
address_last_login = models.CharField(max_length=39, default='', verbose_name=_("Address login"))
@property
def address(self):
@@ -41,7 +41,7 @@ class GatheredAccount(JMSOrgBaseModel):
Account.objects.bulk_create(account_objs)
class Meta:
verbose_name = _('Gather account automation')
verbose_name = _("Gather asset accounts")
unique_together = [
('username', 'asset'),
]
@@ -72,4 +72,4 @@ class GatherAccountsAutomation(AccountBaseAutomation):
super().save(*args, **kwargs)
class Meta:
verbose_name = _("Gather asset accounts")
verbose_name = _('Gather account automation')

View File

@@ -137,16 +137,13 @@ class BaseAccount(VaultModelMixin, JMSOrgBaseModel):
else:
return None
@property
def private_key_path(self):
def get_private_key_path(self, path):
if self.secret_type != SecretType.SSH_KEY \
or not self.secret \
or not self.private_key:
return None
project_dir = settings.PROJECT_DIR
tmp_dir = os.path.join(project_dir, 'tmp')
key_name = '.' + md5(self.private_key.encode('utf-8')).hexdigest()
key_path = os.path.join(tmp_dir, key_name)
key_path = os.path.join(path, key_name)
if not os.path.exists(key_path):
# https://github.com/ansible/ansible-runner/issues/544
# ssh requires OpenSSH format keys to have a full ending newline.
@@ -158,6 +155,12 @@ class BaseAccount(VaultModelMixin, JMSOrgBaseModel):
os.chmod(key_path, 0o400)
return key_path
@property
def private_key_path(self):
project_dir = settings.PROJECT_DIR
tmp_dir = os.path.join(project_dir, 'tmp')
return self.get_private_key_path(tmp_dir)
def get_private_key(self):
if not self.private_key:
return None

View File

@@ -29,7 +29,6 @@ class AccountTemplate(LabeledMixin, BaseAccount, SecretWithRandomMixin):
)
permissions = [
('view_accounttemplatesecret', _('Can view asset account template secret')),
('change_accounttemplatesecret', _('Can change asset account template secret')),
]
def __str__(self):

View File

@@ -15,6 +15,7 @@ class VirtualAccount(JMSOrgBaseModel):
class Meta:
unique_together = [('alias', 'org_id')]
verbose_name = _('Virtual account')
@property
def name(self):

View File

@@ -1,6 +1,7 @@
from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _
from accounts.models import ChangeSecretRecord
from common.tasks import send_mail_attachment_async, upload_backup_to_obj_storage
from notifications.notifications import UserMessage
from terminal.models.component.storage import ReplayStorage
@@ -98,3 +99,35 @@ class GatherAccountChangeMsg(UserMessage):
def gen_test_msg(cls):
user = User.objects.first()
return cls(user, {})
class ChangeSecretFailedMsg(UserMessage):
subject = _('Change secret or push account failed information')
def __init__(self, name, execution_id, user, asset_account_errors: list):
self.name = name
self.execution_id = execution_id
self.asset_account_errors = asset_account_errors
super().__init__(user)
def get_html_msg(self) -> dict:
context = {
'name': self.name,
'recipient': self.user,
'execution_id': self.execution_id,
'asset_account_errors': self.asset_account_errors
}
message = render_to_string('accounts/change_secret_failed_info.html', context)
return {
'subject': str(self.subject),
'message': message
}
@classmethod
def gen_test_msg(cls):
name = 'test'
user = User.objects.first()
record = ChangeSecretRecord.objects.first()
execution_id = str(record.execution_id)
return cls(name, execution_id, user, [])

View File

@@ -31,7 +31,9 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
default=False, label=_("Push now"), write_only=True
)
params = serializers.JSONField(
decoder=None, encoder=None, required=False, style={'base_template': 'textarea.html'}
decoder=None, encoder=None, required=False,
style={'base_template': 'textarea.html'},
label=_('Params'),
)
on_invalid = LabeledChoiceField(
choices=AccountInvalidPolicy.choices, default=AccountInvalidPolicy.ERROR,
@@ -81,7 +83,7 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
def get_template_attr_for_account(template):
# Set initial data from template
field_names = [
'name', 'username', 'secret',
'name', 'username', 'secret', 'push_params',
'secret_type', 'privileged', 'is_active'
]
@@ -90,7 +92,10 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
value = getattr(template, name, None)
if value is None:
continue
attrs[name] = value
if name == 'push_params':
attrs['params'] = value
else:
attrs[name] = value
attrs['secret'] = template.get_secret()
return attrs
@@ -431,8 +436,11 @@ class AssetAccountBulkSerializer(
class AccountSecretSerializer(SecretReadableMixin, AccountSerializer):
class Meta(AccountSerializer.Meta):
fields = AccountSerializer.Meta.fields + ['spec_info']
extra_kwargs = {
**AccountSerializer.Meta.extra_kwargs,
'secret': {'write_only': False},
'spec_info': {'label': _('Spec info')},
}

View File

@@ -35,8 +35,7 @@ class AccountBackupSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSer
]
extra_kwargs = {
'name': {'required': True},
'periodic_display': {'label': _('Periodic perform')},
'executed_amount': {'label': _('Executed amount')},
'executed_amount': {'label': _('Executions')},
'recipients': {
'label': _('Recipient'),
'help_text': _('Currently only mail sending is supported')

View File

@@ -9,26 +9,34 @@ from common.serializers import ResourceLabelsMixin
from common.serializers.fields import EncryptedField, LabeledChoiceField
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
__all__ = ['AuthValidateMixin', 'BaseAccountSerializer']
__all__ = ["AuthValidateMixin", "BaseAccountSerializer"]
class AuthValidateMixin(serializers.Serializer):
secret_type = LabeledChoiceField(
choices=SecretType.choices, label=_('Secret type'), default='password'
choices=SecretType.choices, label=_("Secret type"), default="password"
)
secret = EncryptedField(
label=_('Secret'), required=False, max_length=40960, allow_blank=True,
allow_null=True, write_only=True,
label=_("Secret"),
required=False,
max_length=40960,
allow_blank=True,
allow_null=True,
write_only=True,
)
passphrase = serializers.CharField(
allow_blank=True, allow_null=True, required=False, max_length=512,
write_only=True, label=_('Key password')
allow_blank=True,
allow_null=True,
required=False,
max_length=512,
write_only=True,
label=_("Passphrase"),
)
@staticmethod
def handle_secret(secret, secret_type, passphrase=None):
if not secret:
return ''
return ""
if secret_type == SecretType.PASSWORD:
validate_password_for_ansible(secret)
return secret
@@ -40,17 +48,15 @@ class AuthValidateMixin(serializers.Serializer):
return secret
def clean_auth_fields(self, validated_data):
secret_type = validated_data.get('secret_type')
passphrase = validated_data.get('passphrase')
secret = validated_data.pop('secret', None)
validated_data['secret'] = self.handle_secret(
secret, secret_type, passphrase
)
for field in ('secret',):
secret_type = validated_data.get("secret_type")
passphrase = validated_data.get("passphrase")
secret = validated_data.pop("secret", None)
validated_data["secret"] = self.handle_secret(secret, secret_type, passphrase)
for field in ("secret",):
value = validated_data.get(field)
if not value:
validated_data.pop(field, None)
validated_data.pop('passphrase', None)
validated_data.pop("passphrase", None)
def create(self, validated_data):
self.clean_auth_fields(validated_data)
@@ -61,23 +67,34 @@ class AuthValidateMixin(serializers.Serializer):
return super().update(instance, validated_data)
class BaseAccountSerializer(AuthValidateMixin, ResourceLabelsMixin, BulkOrgResourceModelSerializer):
class BaseAccountSerializer(
AuthValidateMixin, ResourceLabelsMixin, BulkOrgResourceModelSerializer
):
class Meta:
model = BaseAccount
fields_mini = ['id', 'name', 'username']
fields_mini = ["id", "name", "username"]
fields_small = fields_mini + [
'secret_type', 'secret', 'passphrase',
'privileged', 'is_active', 'spec_info',
"secret_type",
"secret",
"passphrase",
"privileged",
"is_active",
"spec_info",
]
fields_other = ['created_by', 'date_created', 'date_updated', 'comment']
fields = fields_small + fields_other + ['labels']
fields_other = ["created_by", "date_created", "date_updated", "comment"]
fields = fields_small + fields_other + ["labels"]
read_only_fields = [
'spec_info', 'date_verified', 'created_by', 'date_created',
"spec_info",
"date_verified",
"created_by",
"date_created",
]
extra_kwargs = {
'spec_info': {'label': _('Spec info')},
'username': {'help_text': _(
"Tip: If no username is required for authentication, fill in `null`, "
"If AD account, like `username@domain`"
)},
"spec_info": {"label": _("Spec info")},
"username": {
"help_text": _(
"* If no username is required for authentication, enter null. "
"For AD accounts, use the format username@domain."
)
},
}

View File

@@ -35,6 +35,7 @@ class AccountTemplateSerializer(BaseAccountSerializer):
'su_from'
]
extra_kwargs = {
**BaseAccountSerializer.Meta.extra_kwargs,
'secret_strategy': {'help_text': _('Secret generation strategy for account creation')},
'auto_push': {'help_text': _('Whether to automatically push the account to the asset')},
'platforms': {
@@ -64,6 +65,9 @@ class AccountTemplateSerializer(BaseAccountSerializer):
class AccountTemplateSecretSerializer(SecretReadableMixin, AccountTemplateSerializer):
class Meta(AccountTemplateSerializer.Meta):
fields = AccountTemplateSerializer.Meta.fields + ['spec_info']
extra_kwargs = {
**AccountTemplateSerializer.Meta.extra_kwargs,
'secret': {'write_only': False},
'spec_info': {'label': _('Spec info')},
}

View File

@@ -21,10 +21,12 @@ __all__ = [
class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSerializer):
assets = ObjectRelatedField(many=True, required=False, queryset=Asset.objects, label=_('Assets'))
nodes = ObjectRelatedField(many=True, required=False, queryset=Node.objects, label=_('Nodes'))
is_periodic = serializers.BooleanField(default=False, required=False, label=_("Periodic perform"))
class Meta:
read_only_fields = [
'date_created', 'date_updated', 'created_by', 'periodic_display', 'executed_amount'
'date_created', 'date_updated', 'created_by',
'periodic_display', 'executed_amount'
]
fields = read_only_fields + [
'id', 'name', 'is_periodic', 'interval', 'crontab', 'comment',
@@ -33,8 +35,7 @@ class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSe
extra_kwargs = {
'name': {'required': True},
'type': {'read_only': True},
'periodic_display': {'label': _('Periodic perform')},
'executed_amount': {'label': _('Executed amount')},
'executed_amount': {'label': _('Executions')},
}
def validate_name(self, name):

View File

@@ -4,7 +4,8 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from accounts.const import (
AutomationTypes, SecretType, SecretStrategy, SSHKeyStrategy
AutomationTypes, SecretType, SecretStrategy,
SSHKeyStrategy, ChangeSecretRecordStatusChoice
)
from accounts.models import (
Account, ChangeSecretAutomation,
@@ -21,6 +22,7 @@ logger = get_logger(__file__)
__all__ = [
'ChangeSecretAutomationSerializer',
'ChangeSecretRecordSerializer',
'ChangeSecretRecordViewSecretSerializer',
'ChangeSecretRecordBackUpSerializer',
'ChangeSecretUpdateAssetSerializer',
'ChangeSecretUpdateNodeSerializer',
@@ -52,10 +54,13 @@ class ChangeSecretAutomationSerializer(AuthValidateMixin, BaseAutomationSerializ
'ssh_key_change_strategy', 'passphrase', 'recipients', 'params'
]
extra_kwargs = {**BaseAutomationSerializer.Meta.extra_kwargs, **{
'accounts': {'required': True},
'accounts': {'required': True, 'help_text': _('Please enter your account username')},
'recipients': {'label': _('Recipient'), 'help_text': _(
"Currently only mail sending is supported"
)},
'params': {'help_text': _(
"Secret parameter settings, currently only effective for assets of the host type."
)},
}}
@property
@@ -104,7 +109,10 @@ class ChangeSecretAutomationSerializer(AuthValidateMixin, BaseAutomationSerializ
class ChangeSecretRecordSerializer(serializers.ModelSerializer):
is_success = serializers.SerializerMethodField(label=_('Is success'))
asset = ObjectRelatedField(queryset=Asset.objects, label=_('Asset'))
account = ObjectRelatedField(queryset=Account.objects, label=_('Account'))
account = ObjectRelatedField(
queryset=Account.objects, label=_('Account'),
attrs=("id", "name", "username")
)
execution = ObjectRelatedField(
queryset=AutomationExecution.objects, label=_('Automation task execution')
)
@@ -119,7 +127,16 @@ class ChangeSecretRecordSerializer(serializers.ModelSerializer):
@staticmethod
def get_is_success(obj):
return obj.status == 'success'
return obj.status == ChangeSecretRecordStatusChoice.success.value
class ChangeSecretRecordViewSecretSerializer(serializers.ModelSerializer):
class Meta:
model = ChangeSecretRecord
fields = [
'id', 'old_secret', 'new_secret',
]
read_only_fields = fields
class ChangeSecretRecordBackUpSerializer(serializers.ModelSerializer):
@@ -145,7 +162,7 @@ class ChangeSecretRecordBackUpSerializer(serializers.ModelSerializer):
@staticmethod
def get_is_success(obj):
if obj.status == 'success':
if obj.status == ChangeSecretRecordStatusChoice.success.value:
return _("Success")
return _("Failed")

View File

@@ -7,7 +7,6 @@ from .change_secret import (
class PushAccountAutomationSerializer(ChangeSecretAutomationSerializer):
class Meta(ChangeSecretAutomationSerializer.Meta):
model = PushAccountAutomation
fields = [

View File

@@ -36,14 +36,14 @@ def execute_account_automation_task(pid, trigger, tp):
instance.execute(trigger)
def record_task_activity_callback(self, record_id, *args, **kwargs):
def record_task_activity_callback(self, record_ids, *args, **kwargs):
from accounts.models import ChangeSecretRecord
with tmp_to_root_org():
record = get_object_or_none(ChangeSecretRecord, id=record_id)
if not record:
records = ChangeSecretRecord.objects.filter(id__in=record_ids)
if not records:
return
resource_ids = [record.id]
org_id = record.execution.org_id
resource_ids = [str(i.id) for i in records]
org_id = records[0].execution.org_id
return resource_ids, org_id
@@ -51,22 +51,26 @@ def record_task_activity_callback(self, record_id, *args, **kwargs):
queue='ansible', verbose_name=_('Execute automation record'),
activity_callback=record_task_activity_callback
)
def execute_automation_record_task(record_id, tp):
def execute_automation_record_task(record_ids, tp):
from accounts.models import ChangeSecretRecord
task_name = gettext_noop('Execute automation record')
with tmp_to_root_org():
instance = get_object_or_none(ChangeSecretRecord, pk=record_id)
if not instance:
logger.error("No automation record found: {}".format(record_id))
records = ChangeSecretRecord.objects.filter(id__in=record_ids)
if not records:
logger.error('No automation record found: {}'.format(record_ids))
return
task_name = gettext_noop('Execute automation record')
record = records[0]
record_map = {f'{record.asset_id}-{record.account_id}': str(record.id) for record in records}
task_snapshot = {
'secret': instance.new_secret,
'secret_type': instance.execution.snapshot.get('secret_type'),
'accounts': [str(instance.account_id)],
'assets': [str(instance.asset_id)],
'params': {},
'record_id': record_id,
'record_map': record_map,
'secret': record.new_secret,
'secret_type': record.execution.snapshot.get('secret_type'),
'assets': [str(instance.asset_id) for instance in records],
'accounts': [str(instance.account_id) for instance in records],
}
with tmp_to_org(instance.execution.org_id):
with tmp_to_org(record.execution.org_id):
quickstart_automation_by_snapshot(task_name, tp, task_snapshot)

View File

@@ -55,7 +55,7 @@ def clean_historical_accounts():
history_model = Account.history.model
history_id_mapper = defaultdict(list)
ids = history_model.objects.values('id').annotate(count=Count('id', distinct=True)) \
ids = history_model.objects.values('id').annotate(count=Count('id')) \
.filter(count__gte=limit).values_list('id', flat=True)
if not ids:

View File

@@ -29,7 +29,8 @@ def template_sync_related_accounts(template_id, user_id=None):
name = template.name
username = template.username
secret_type = template.secret_type
print(f'\033[32m>>> 开始同步模版名称、用户名、密钥类型到相关联的账号 ({datetime.now().strftime("%Y-%m-%d %H:%M:%S")})')
print(
f'\033[32m>>> 开始同步模板名称、用户名、密钥类型到相关联的账号 ({datetime.now().strftime("%Y-%m-%d %H:%M:%S")})')
with tmp_to_org(org_id):
for account in accounts:
account.name = name

View File

@@ -1,10 +1,10 @@
{% load i18n %}
<h3>{% trans 'Gather account change information' %}</h3>
<table style="width: 100%; border-collapse: collapse; max-width: 100%; text-align: left; margin-top: 20px;">
<caption></caption>
<tr style="background-color: #f2f2f2;">
<th style="border: 1px solid #ddd; padding: 10px; font-weight: bold;">{% trans 'Asset' %}</th>
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Asset' %}</th>
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Added account' %}</th>
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Deleted account' %}</th>
</tr>

View File

@@ -0,0 +1,36 @@
{% load i18n %}
<h3>{% trans 'Task name' %}: {{ name }}</h3>
<h3>{% trans 'Task execution id' %}: {{ execution_id }}</h3>
<p>{% trans 'Respectful' %} {{ recipient }}</p>
<p>{% trans 'Hello! The following is the failure of changing the password of your assets or pushing the account. Please check and handle it in time.' %}</p>
<table style="width: 100%; border-collapse: collapse; max-width: 100%; text-align: left; margin-top: 20px;">
<caption></caption>
<thead>
<tr style="background-color: #f2f2f2;">
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Asset' %}</th>
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Account' %}</th>
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Error' %}</th>
</tr>
</thead>
<tbody>
{% for asset_name, account_username, error in asset_account_errors %}
<tr>
<td style="border: 1px solid #ddd; padding: 10px;">{{ asset_name }}</td>
<td style="border: 1px solid #ddd; padding: 10px;">{{ account_username }}</td>
<td style="border: 1px solid #ddd; padding: 10px;">
<div style="
max-width: 90%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;"
title="{{ error }}"
>
{{ error }}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@@ -4,4 +4,4 @@ from django.utils.translation import gettext_lazy as _
class AclsConfig(AppConfig):
name = 'acls'
verbose_name = _('Acls')
verbose_name = _('App Acls')

View File

@@ -6,5 +6,5 @@ class ActionChoices(models.TextChoices):
reject = 'reject', _('Reject')
accept = 'accept', _('Accept')
review = 'review', _('Review')
warning = 'warning', _('Warning')
notice = 'notice', _('Notifications')
warning = 'warning', _('Warn')
notice = 'notice', _('Notify')

View File

@@ -1,75 +1,129 @@
# Generated by Django 3.1 on 2021-03-11 09:53
import uuid
# Generated by Django 4.1.13 on 2024-05-09 03:16
import common.db.fields
import django.core.validators
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='LoginACL',
name='CommandFilterACL',
fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first',
validators=[django.core.validators.MinValueValidator(1),
django.core.validators.MaxValueValidator(100)],
verbose_name='Priority')),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('ip_group', models.JSONField(default=list, verbose_name='Login IP')),
('action',
models.CharField(choices=[('reject', 'Reject'), ('allow', 'Allow')], default='reject', max_length=64,
verbose_name='Action')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='login_acls',
to=settings.AUTH_USER_MODEL, verbose_name='User')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')),
('action', models.CharField(default='reject', max_length=64, verbose_name='Action')),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('assets', common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets')),
('accounts', models.JSONField(default=list, verbose_name='Accounts')),
],
options={
'verbose_name': 'Command acl',
'ordering': ('priority', '-is_active', 'name'),
'abstract': False,
},
),
migrations.CreateModel(
name='CommandGroup',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('type', models.CharField(choices=[('command', 'Command'), ('regex', 'Regex')], default='command', max_length=16, verbose_name='Type')),
('content', models.TextField(help_text='One command per line', verbose_name='Content')),
('ignore_case', models.BooleanField(default=True, verbose_name='Ignore case')),
],
options={
'verbose_name': 'Command group',
},
),
migrations.CreateModel(
name='ConnectMethodACL',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('name', models.CharField(max_length=128, unique=True, verbose_name='Name')),
('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')),
('action', models.CharField(default='reject', max_length=64, verbose_name='Action')),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')),
('connect_methods', models.JSONField(default=list, verbose_name='Connect methods')),
],
options={
'verbose_name': 'Connect method acl',
'ordering': ('priority', '-is_active', 'name'),
'abstract': False,
},
),
migrations.CreateModel(
name='LoginACL',
fields=[
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('name', models.CharField(max_length=128, unique=True, verbose_name='Name')),
('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')),
('action', models.CharField(default='reject', max_length=64, verbose_name='Action')),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')),
('rules', models.JSONField(default=dict, verbose_name='Rule')),
],
options={
'verbose_name': 'Login acl',
'ordering': ('priority', '-is_active', 'name'),
'abstract': False,
},
),
migrations.CreateModel(
name='LoginAssetACL',
fields=[
('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first',
validators=[django.core.validators.MinValueValidator(1),
django.core.validators.MaxValueValidator(100)],
verbose_name='Priority')),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('users', models.JSONField(verbose_name='User')),
('system_users', models.JSONField(verbose_name='System User')),
('assets', models.JSONField(verbose_name='Asset')),
('action',
models.CharField(choices=[('login_confirm', 'Login confirm')], default='login_confirm', max_length=64,
verbose_name='Action')),
('reviewers',
models.ManyToManyField(blank=True, related_name='review_login_asset_acls', to=settings.AUTH_USER_MODEL,
verbose_name='Reviewers')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')),
('action', models.CharField(default='reject', max_length=64, verbose_name='Action')),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('assets', common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets')),
('accounts', models.JSONField(default=list, verbose_name='Accounts')),
('rules', models.JSONField(default=dict, verbose_name='Rule')),
],
options={
'verbose_name': 'Login asset acl',
'ordering': ('priority', '-is_active', 'name'),
'unique_together': {('name', 'org_id')},
'abstract': False,
},
),
]

View File

@@ -1,98 +1,54 @@
# Generated by Django 3.1.12 on 2021-09-26 02:47
import django
# Generated by Django 4.1.13 on 2024-05-09 03:16
from django.conf import settings
from django.db import migrations, models, transaction
LOGIN_CONFIRM_ZH = '登录复核'
LOGIN_CONFIRM_EN = 'Login confirm'
DEFAULT_TIME_PERIODS = [{'id': i, 'value': '00:00~00:00'} for i in range(7)]
def has_zh(name: str) -> bool:
for i in name:
if u'\u4e00' <= i <= u'\u9fff':
return True
return False
def migrate_login_confirm(apps, schema_editor):
login_acl_model = apps.get_model("acls", "LoginACL")
login_confirm_model = apps.get_model("authentication", "LoginConfirmSetting")
with transaction.atomic():
for instance in login_confirm_model.objects.filter(is_active=True):
user = instance.user
reviewers = instance.reviewers.all()
login_confirm = LOGIN_CONFIRM_ZH if has_zh(user.name) else LOGIN_CONFIRM_EN
date_created = instance.date_created.strftime('%Y-%m-%d %H:%M:%S')
if reviewers.count() == 0:
continue
data = {
'user': user,
'name': f'{user.name}-{login_confirm} ({date_created})',
'created_by': instance.created_by,
'action': 'confirm',
'rules': {'ip_group': ['*'], 'time_period': DEFAULT_TIME_PERIODS}
}
instance = login_acl_model.objects.create(**data)
instance.reviewers.set(reviewers)
def migrate_ip_group(apps, schema_editor):
login_acl_model = apps.get_model("acls", "LoginACL")
updates = list()
with transaction.atomic():
for instance in login_acl_model.objects.exclude(action='confirm'):
instance.rules = {'ip_group': instance.ip_group, 'time_period': DEFAULT_TIME_PERIODS}
updates.append(instance)
login_acl_model.objects.bulk_update(updates, ['rules', ])
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('acls', '0001_initial'),
('authentication', '0004_ssotoken'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterField(
model_name='loginacl',
name='action',
field=models.CharField(choices=[('reject', 'Reject'), ('allow', 'Allow'), ('confirm', 'Login confirm')],
default='reject', max_length=64, verbose_name='Action'),
migrations.AddField(
model_name='loginassetacl',
name='reviewers',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'),
),
migrations.AddField(
model_name='loginacl',
name='reviewers',
field=models.ManyToManyField(blank=True, related_name='login_confirm_acls',
to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'),
),
migrations.AlterField(
model_name='loginacl',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
related_name='login_acls', to=settings.AUTH_USER_MODEL, verbose_name='User'),
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'),
),
migrations.AddField(
model_name='loginacl',
name='rules',
field=models.JSONField(default=dict, verbose_name='Rule'),
model_name='connectmethodacl',
name='reviewers',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'),
),
migrations.RunPython(migrate_login_confirm),
migrations.RunPython(migrate_ip_group),
migrations.RemoveField(
model_name='loginacl',
name='ip_group',
migrations.AlterUniqueTogether(
name='commandgroup',
unique_together={('org_id', 'name')},
),
migrations.AlterModelOptions(
name='loginacl',
options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login acl'},
migrations.AddField(
model_name='commandfilteracl',
name='command_groups',
field=models.ManyToManyField(related_name='command_filters', to='acls.commandgroup', verbose_name='Command group'),
),
migrations.AlterModelOptions(
migrations.AddField(
model_name='commandfilteracl',
name='reviewers',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'),
),
migrations.AlterUniqueTogether(
name='loginassetacl',
options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login asset acl'},
unique_together={('name', 'org_id')},
),
migrations.AlterUniqueTogether(
name='commandfilteracl',
unique_together={('name', 'org_id')},
),
]

View File

@@ -1,20 +0,0 @@
# Generated by Django 3.1.13 on 2021-11-30 02:37
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('acls', '0002_auto_20210926_1047'),
]
operations = [
migrations.AlterModelOptions(
name='loginacl',
options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login acl'},
),
migrations.AlterModelOptions(
name='loginassetacl',
options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login asset acl'},
),
]

View File

@@ -1,33 +0,0 @@
# Generated by Django 3.2.13 on 2022-08-31 08:58
from django.db import migrations, models
def migrate_system_users_to_accounts(apps, schema_editor):
login_asset_acl_model = apps.get_model('acls', 'LoginAssetACL')
qs = login_asset_acl_model.objects.all()
login_asset_acls = []
for instance in qs:
instance.accounts = instance.system_users
login_asset_acls.append(instance)
login_asset_acl_model.objects.bulk_update(login_asset_acls, ['accounts'])
class Migration(migrations.Migration):
dependencies = [
('acls', '0003_auto_20211130_1037'),
]
operations = [
migrations.AddField(
model_name='loginassetacl',
name='accounts',
field=models.JSONField(verbose_name='Account'),
),
migrations.RunPython(migrate_system_users_to_accounts),
migrations.RemoveField(
model_name='loginassetacl',
name='system_users',
),
]

View File

@@ -1,34 +0,0 @@
# Generated by Django 3.2.14 on 2022-12-01 10:46
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('acls', '0004_auto_20220831_1658'),
]
operations = [
migrations.AlterField(
model_name='loginacl',
name='action',
field=models.CharField(default='reject', max_length=64, verbose_name='Action'),
),
migrations.AlterField(
model_name='loginacl',
name='reviewers',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'),
),
migrations.AlterField(
model_name='loginassetacl',
name='action',
field=models.CharField(default='reject', max_length=64, verbose_name='Action'),
),
migrations.AlterField(
model_name='loginassetacl',
name='reviewers',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'),
),
]

View File

@@ -1,70 +0,0 @@
# Generated by Django 3.2.14 on 2022-12-01 11:39
import uuid
import django.core.validators
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('acls', '0005_auto_20221201_1846'),
]
operations = [
migrations.CreateModel(
name='CommandGroup',
fields=[
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('type', models.CharField(choices=[('command', 'Command'), ('regex', 'Regex')], default='command',
max_length=16, verbose_name='Type')),
('content', models.TextField(help_text='One line one command', verbose_name='Content')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('ignore_case', models.BooleanField(default=True, verbose_name='Ignore case')),
],
options={
'verbose_name': 'Command filter rule',
'unique_together': {('org_id', 'name')},
},
),
migrations.CreateModel(
name='CommandFilterACL',
fields=[
('org_id',
models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first',
validators=[django.core.validators.MinValueValidator(1),
django.core.validators.MaxValueValidator(100)],
verbose_name='Priority')),
('action', models.CharField(default='reject', max_length=64, verbose_name='Action')),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('users', models.JSONField(verbose_name='User')),
('accounts', models.JSONField(verbose_name='Account')),
('assets', models.JSONField(verbose_name='Asset')),
('commands', models.ManyToManyField(to='acls.CommandGroup', verbose_name='Commands')),
(
'reviewers',
models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers')),
],
options={
'verbose_name': 'Command acl',
'ordering': ('priority', '-is_active', 'name'),
'unique_together': {('name', 'org_id')},
},
),
]

View File

@@ -1,21 +0,0 @@
# Generated by Django 3.2.14 on 2022-12-02 02:48
from django.db import migrations
def migrate_login_type(apps, schema_editor):
login_asset_model = apps.get_model('acls', 'LoginAssetACL')
login_asset_model.objects.filter(action='login_confirm').update(action='review')
login_system_model = apps.get_model('acls', 'LoginACL')
login_system_model.objects.filter(action='confirm').update(action='review')
class Migration(migrations.Migration):
dependencies = [
('acls', '0006_commandfilteracl_commandgroup'),
]
operations = [
migrations.RunPython(migrate_login_type),
]

View File

@@ -1,33 +0,0 @@
# Generated by Django 3.2.14 on 2022-12-02 04:25
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('acls', '0007_auto_20221202_1048'),
]
operations = [
migrations.AlterModelOptions(
name='commandgroup',
options={'verbose_name': 'Command group'},
),
migrations.RenameField(
model_name='commandfilteracl',
old_name='commands',
new_name='command_groups',
),
migrations.AlterModelOptions(
name='commandfilteracl',
options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Command acl'},
),
migrations.AlterModelOptions(
name='loginacl',
options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login acl'},
),
migrations.AlterModelOptions(
name='loginassetacl',
options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login asset acl'},
),
]

View File

@@ -1,53 +0,0 @@
# Generated by Django 3.2.14 on 2022-12-20 11:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('acls', '0008_commandgroup_comment'),
]
operations = [
migrations.AddField(
model_name='commandfilteracl',
name='updated_by',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'),
),
migrations.AddField(
model_name='loginacl',
name='updated_by',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'),
),
migrations.AddField(
model_name='loginassetacl',
name='updated_by',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'),
),
migrations.AlterField(
model_name='commandfilteracl',
name='created_by',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'),
),
migrations.AlterField(
model_name='commandgroup',
name='created_by',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'),
),
migrations.AlterField(
model_name='commandgroup',
name='updated_by',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'),
),
migrations.AlterField(
model_name='loginacl',
name='created_by',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'),
),
migrations.AlterField(
model_name='loginassetacl',
name='created_by',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'),
),
]

View File

@@ -1,18 +0,0 @@
# Generated by Django 3.2.16 on 2023-01-10 06:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('acls', '0009_auto_20221220_1956'),
]
operations = [
migrations.AlterField(
model_name='commandfilteracl',
name='command_groups',
field=models.ManyToManyField(to='acls.CommandGroup', verbose_name='Command group'),
),
]

View File

@@ -1,44 +0,0 @@
# Generated by Django 3.2.17 on 2023-04-25 09:04
from django.db import migrations, models
import common.db.fields
class Migration(migrations.Migration):
dependencies = [
('acls', '0010_alter_commandfilteracl_command_groups'),
]
operations = [
migrations.AddField(
model_name='commandfilteracl',
name='new_accounts',
field=models.JSONField(default=list, verbose_name='Accounts'),
),
migrations.AddField(
model_name='commandfilteracl',
name='new_assets',
field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets'),
),
migrations.AddField(
model_name='commandfilteracl',
name='new_users',
field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'),
),
migrations.AddField(
model_name='loginassetacl',
name='new_accounts',
field=models.JSONField(default=list, verbose_name='Accounts')
),
migrations.AddField(
model_name='loginassetacl',
name='new_assets',
field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets'),
),
migrations.AddField(
model_name='loginassetacl',
name='new_users',
field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'),
),
]

Some files were not shown because too many files have changed in this diff Show More