Compare commits

...

191 Commits
0.1.0 ... 0.1.1

Author SHA1 Message Date
ibuler
aba3a2222d Merge branch 'master' of https://github.com/xxrenzhe/jumpserver 2014-12-07 21:09:03 +08:00
xxrenzhe
a49b944e29 Adjust a equal judgement 2014-12-07 20:43:13 +08:00
guanghongwei
333e2a20ff 修改了初始连接屏幕大小的bug 2014-11-20 14:43:38 +08:00
蓝枫
59c770a3bf Update README.md 2014-11-15 14:39:26 +08:00
蓝枫
df5227d48a Update README.md 2014-11-15 14:37:57 +08:00
蓝枫
8d0bf4c625 Update README.md 2014-11-15 14:23:52 +08:00
蓝枫
d1238efb6f Update README.md 2014-11-15 14:23:11 +08:00
蓝枫
8fcccbb8bc Update README.md 2014-11-15 14:21:36 +08:00
蓝枫
313a20d189 Update README.md 2014-11-15 14:17:30 +08:00
蓝枫
9c4fb88b7a Update README.md 2014-11-15 14:10:04 +08:00
蓝枫
3c1b1b18e4 Update README.md
update
2014-11-15 14:07:19 +08:00
蓝枫
0d7f65db1c Update README.md
删除原来的README.md
2014-11-14 17:07:29 +08:00
guanghongwei
ea39dfb415 delete conf from jumpserver.py 2014-11-13 14:59:05 +08:00
guanghongwei
9f9b08f6bc rm pyc file 2014-11-13 11:40:04 +08:00
guanghongwei
52a98b11e7 bugfix 2014-11-13 10:38:18 +08:00
root
f6d414d903 fix bug 2014-11-12 11:00:47 +08:00
ibuler
eae5535b42 bugfix 2014-11-12 23:44:17 +08:00
ibuler
d9d3f25dfd bugfix 2014-11-12 21:53:03 +08:00
guanghongwei
d6b6e745b2 fixbug 2014-11-12 19:10:23 +08:00
guanghongwei
f903750d58 fixbug 2014-11-12 18:54:30 +08:00
guanghongwei
61ac985e09 修改bug 2014-11-12 18:45:26 +08:00
guanghongwei
22c7cb6c7d Merge branch 'dev' of ssh://172.10.10.9:2001/opt/jumpserver into dev 2014-11-12 18:28:00 +08:00
guanghongwei
24415f5b24 bugfix 2014-11-12 18:25:09 +08:00
宿召阳
931ac3dd1f bug fix 2014-11-12 18:21:34 +08:00
guanghongwei
99313cd2db bugfix 2014-11-12 18:11:43 +08:00
guanghongwei
7e6a4621c5 bugfix 2014-11-12 17:56:56 +08:00
guanghongwei
fa2358d22b bugfix 2014-11-12 17:54:04 +08:00
guanghongwei
0f63eadfc1 bugfix 2014-11-12 17:52:56 +08:00
宿召阳
4844f7861b bug fix 2014-11-12 17:41:14 +08:00
guanghongwei
9ad9a8812f 删除tsst 2014-11-12 15:55:44 +08:00
guanghongwei
d036ef7f0a Merge branch 'dev' of ssh://172.10.10.9:2001/opt/jumpserver into dev 2014-11-12 15:54:53 +08:00
ibuler
b211856394 abc 2014-11-12 15:54:18 +08:00
ibuler
71299df131 add websocket 2014-11-12 15:50:04 +08:00
ibuler
6bacda6a9a add websocket 2014-11-12 15:48:33 +08:00
ibuler
dc782ca5b5 add websocket 2014-11-12 15:38:26 +08:00
ibuler
4a9923db4b bug fix 2014-11-11 23:40:26 +08:00
ibuler
9d7641ad8a 删除没用的模块 2014-11-11 21:35:26 +08:00
ibuler
a7904a8d57 修改一些bug 2014-11-11 17:29:11 +08:00
ibuler
a4e6fef2a6 修改名称 2014-11-11 14:17:03 +08:00
ibuler
6c762b865a bugfix 2014-11-11 00:05:50 +08:00
ibuler
c424cad244 bugfix 2014-11-10 23:46:20 +08:00
ibuler
16ec34c463 bugfix 2014-11-10 23:42:45 +08:00
ibuler
44ef066ede bugfix 2014-11-10 23:41:38 +08:00
ibuler
f947a753db bugfix 2014-11-10 23:36:52 +08:00
ibuler
532cefe338 bug fix 2014-11-10 23:35:12 +08:00
ibuler
62bc814a44 bug fix 2014-11-10 23:31:43 +08:00
ibuler
dc11f34585 添加IDC的支持 2014-11-10 23:28:44 +08:00
ibuler
a5c3048a89 1. 支持绝对路径
2. 支持分页
2014-11-09 22:25:55 +08:00
宿召阳
41b7110554 bug fix 2014-11-07 16:12:45 +08:00
宿召阳
d38a963dbd bug fix 2014-11-07 15:50:37 +08:00
宿召阳
b1aff5c997 bug fix 2014-11-07 15:44:50 +08:00
宿召阳
f5b02265a4 bug fix 2014-11-07 15:38:19 +08:00
宿召阳
21ab6cbe1e bug fix 2014-11-07 15:36:25 +08:00
宿召阳
0560ccaf17 bug fix' 2014-11-07 15:33:41 +08:00
宿召阳
0e3c79fb79 bug fix 2014-11-07 15:18:52 +08:00
宿召阳
1c9359bb4c bug fix 2014-11-07 14:27:05 +08:00
宿召阳
1c4adc1e38 bug fix 2014-11-07 14:12:17 +08:00
宿召阳
a5abd9d620 del 2014-11-07 11:26:38 +08:00
guanghongwei
2ca299a31f 添加忽略文件 2014-11-07 11:00:53 +08:00
宿召阳
1c930b31d9 bug fix 2014-11-07 10:52:08 +08:00
guanghongwei
331f029096 Merge branch 'dev' of ssh://172.10.10.9:2001/opt/jumpserver into dev 2014-11-07 10:50:18 +08:00
guanghongwei
586e2602db 修改bug 2014-11-07 10:48:04 +08:00
宿召阳
83ac653637 merge 2014-11-07 10:30:13 +08:00
宿召阳
d1ea2a6dd1 add ignore 2014-11-07 10:29:35 +08:00
宿召阳
4f2bc9d402 add socket 2014-11-07 10:27:59 +08:00
ibuler
3bee29338c 删除没用的 2014-11-06 23:20:06 +08:00
ibuler
26c31feb4a 修改记录日志bug 2014-11-06 22:56:36 +08:00
guanghongwei
d8e4efe7cc 修改 批量命令记录日志,上传下载记录日志 2014-11-06 18:48:13 +08:00
guanghongwei
fc3d13a4b1 logfile 2014-11-06 17:35:02 +08:00
guanghongwei
d134b2279b 修改 monitor 2014-11-06 17:32:43 +08:00
guanghongwei
f3efa9b914 删除view echo 2014-11-06 13:56:31 +08:00
guanghongwei
9cdd62b62d 删除 django-websocket
添加 requirements.txt
2014-11-06 13:53:12 +08:00
ibuler
271b80991a ok 2014-11-05 00:31:05 +08:00
ibuler
5f302866ca ok 2014-11-05 00:29:04 +08:00
ibuler
cce2bb5590 bug 2014-11-05 00:23:34 +08:00
ibuler
a01c1a40b9 s 2014-11-05 00:21:27 +08:00
ibuler
c82b8f1128 sokcet 2014-11-05 00:15:29 +08:00
ibuler
862cec316f websocket 2014-11-05 00:12:31 +08:00
ibuler
5445e5eaa1 test websocket 2014-11-05 00:11:04 +08:00
ibuler
22bcda23dc websocket 2014-11-04 23:58:20 +08:00
ibuler
fcabb66f2e test websocket 2014-11-04 23:52:06 +08:00
ibuler
5b2911a5ed test websocket 2014-11-04 23:51:16 +08:00
ibuler
969d54050f 修改模板 2014-11-04 21:56:39 +08:00
ibuler
92188f1c77 修改bug 2014-11-04 21:48:34 +08:00
ibuler
c18290c667 kill session 2014-11-04 21:46:19 +08:00
guanghongwei
19b94655fb 删除没用的 2014-11-04 18:46:34 +08:00
guanghongwei
825adba39c bug 2014-11-04 17:25:08 +08:00
guanghongwei
2d28a7a0c4 bug 2014-11-04 17:22:47 +08:00
guanghongwei
4a09ce32e6 修改bug 2014-11-04 17:20:23 +08:00
guanghongwei
0ccb808b3f 修改 2014-11-04 17:18:27 +08:00
guanghongwei
08c30e462c 日志汇总查看 2014-11-04 16:37:48 +08:00
ibuler
654c27490d 添加删除pid条目 2014-11-04 00:22:52 +08:00
ibuler
06e788782b chmod +x log_handler.py 2014-11-04 00:14:19 +08:00
ibuler
7d868c5195 修改位置 2014-11-04 00:12:40 +08:00
ibuler
2212cf24b4 日志处理系统 2014-11-04 00:10:01 +08:00
guanghongwei
d728c06851 修改bug 2014-11-03 10:57:23 +08:00
guanghongwei
b52420708e 修改 mytags位置 2014-11-03 10:45:43 +08:00
ibuler
5bc67ebad9 修改错误 2014-11-02 23:50:19 +08:00
ibuler
a57adf9b2e 更改过滤标签 2014-11-02 23:11:44 +08:00
ibuler
aa9139c642 分页显示 2014-11-02 23:01:36 +08:00
ibuler
efbcacbec6 加入日志审计 2014-11-02 22:54:26 +08:00
ibuler
e5121fe7ea 记录 子pid 2014-11-02 16:25:20 +08:00
ibuler
ac926b5fb4 增加进程pid 2014-11-02 15:23:45 +08:00
ibuler
44166e2653 闹心的 password和ldap_password 2014-11-02 14:36:19 +08:00
ibuler
e38fb5992f sql使用mysql models来完成 2014-11-02 13:36:14 +08:00
ibuler
765ac5e714 记录日志 2014-11-02 00:01:56 +08:00
ibuler
f766ba340f 配置文件修改 2014-11-01 23:12:27 +08:00
ibuler
5b060a768a 修改bug 2014-11-01 22:51:18 +08:00
ibuler
54da30d93b 修改配置文件为相对路径,不用再指定目录了 2014-11-01 22:46:41 +08:00
ibuler
838b10d3b6 Merge branch 'dev' of ssh://172.10.10.9:2001/opt/jumpserver into dev 2014-11-01 16:18:27 +08:00
ibuler
cd84f0d5c6 修改拖动窗口关闭的bug 2014-11-01 16:16:31 +08:00
guanghongwei
641b72f3d1 修改 foo.setwinsize() 2014-10-31 18:42:55 +08:00
guanghongwei
63065f5c33 使用pxssh 2014-10-31 14:35:33 +08:00
ibuler
de2837229c modify logdir , asset beizhu 2014-10-31 00:07:33 +08:00
ibuler
596573293f modify connect_one view 2014-10-30 22:11:45 +08:00
ibuler
93bd02017c add downFile url 2014-10-30 21:42:42 +08:00
ibuler
2e1c7d2fb8 修改模板显示
修改jumpserver.py   1.2 1.21
修改下载大文件
2014-10-30 21:39:03 +08:00
guanghongwei
78b55f981c ok 2014-10-12 21:13:27 +08:00
guanghongwei
fb8b800fd7 上传 2014-10-09 23:12:20 +08:00
guanghongwei
67b0cd5522 上传 2014-10-09 22:55:03 +08:00
guanghongwei
68e8c4ba0f 删除没用的代码,添加上传文件 2014-10-09 22:31:47 +08:00
guanghongwei
1b08c6ea88 修改 2014-10-09 11:26:15 +08:00
guanghongwei
6ae84b3334 修改chgSudo.py 2014-10-09 10:51:01 +08:00
guanghongwei
6418033e51 修改 chgsudo 2014-10-09 10:21:36 +08:00
guanghongwei
f48dd46898 修改chgsudo 2014-10-08 22:42:43 +08:00
guanghongwei
9020c11bd2 修改chgSudo的view 2014-10-08 22:19:53 +08:00
guanghongwei
50b7d00683 修改button属性 2014-10-08 17:59:38 +08:00
guanghongwei
e3078d2ac6 chgSudo修改 2014-10-08 17:56:41 +08:00
guanghongwei
582418797d 修改chgSudo.html 2014-10-08 12:20:31 +08:00
guanghongwei
031b92bf03 修改chgSudo.html 2014-10-08 12:03:10 +08:00
guanghongwei
1a529a7d7f 修改 2014-10-07 19:18:13 +08:00
guanghongwei
f4591e3aad 修改url 2014-10-07 19:08:17 +08:00
guanghongwei
14c48bc1bf sudo显示 2014-10-07 19:04:57 +08:00
guanghongwei
30cbf15b57 sudo ldap时出错 2014-10-07 18:29:04 +08:00
guanghongwei
41dbfbb335 修改一点点 2014-10-07 18:06:36 +08:00
guanghongwei
9191d3b6e5 修改bug 2014-10-03 23:06:28 +08:00
guanghongwei
d0a5274214 is_admin_role 2014-10-03 22:47:41 +08:00
guanghongwei
7f132e100f 各种修改bug 2014-10-03 22:32:49 +08:00
guanghongwei
61fcfb80a8 还是修改bug 2014-10-03 22:18:26 +08:00
guanghongwei
046d4da45c 修改bug 2014-10-03 22:16:51 +08:00
guanghongwei
94830a79a3 修改bug 2014-10-03 22:14:43 +08:00
guanghongwei
bb0a023380 修改group 2014-10-03 22:11:59 +08:00
guanghongwei
c8444ef73a 增加分组 2014-10-03 22:04:36 +08:00
guanghongwei
7c5f2d216f 修改密码 2014-10-01 21:17:54 +08:00
guanghongwei
201ef814f9 修改bug 2014-10-01 21:15:19 +08:00
guanghongwei
00f6984929 修改小错误 2014-10-01 21:12:30 +08:00
guanghongwei
f2e39f24c8 密码没有默认 2014-10-01 21:09:50 +08:00
guanghongwei
cd3f787aef 更改chgKey函数 2014-10-01 21:00:17 +08:00
guanghongwei
86a9c46643 我都想吐了 2014-09-29 20:43:59 +08:00
guanghongwei
d639801f3c 更改 2014-09-29 18:20:41 +08:00
guanghongwei
4517ec0629 修改 2014-09-29 17:32:35 +08:00
guanghongwei
9601476077 maybe车次好了 2014-09-29 17:05:03 +08:00
guanghongwei
e2e067139c 应该是可以修改成功的 2014-09-29 16:53:52 +08:00
guanghongwei
42d130d5c2 bug越来越多 2014-09-29 16:22:30 +08:00
guanghongwei
632b863cf7 太他妈闹心了 2014-09-29 16:16:23 +08:00
guanghongwei
83f8f5a150 最后一次? 2014-09-29 16:07:59 +08:00
guanghongwei
1f272aa03c 一天修改10变 2014-09-29 16:05:53 +08:00
guanghongwei
222162eaa7 继续他妈修改 2014-09-29 16:04:05 +08:00
guanghongwei
102e832a58 我擦 2014-09-29 15:58:25 +08:00
guanghongwei
e8ab3e45f3 尼玛修改文件 2014-09-29 15:55:32 +08:00
guanghongwei
ec4a9e92bf 修改bug 2014-09-29 15:35:05 +08:00
guanghongwei
16a2d3803a 修改chgUser.html 2014-09-29 15:27:17 +08:00
guanghongwei
4d58d9ef0e 修改用户信息 2014-09-29 09:30:57 +08:00
guanghongwei
a263e50b3e jm忘记加参数了 2014-09-28 16:32:55 +08:00
guanghongwei
6e2ebd5c79 修改 修改用户信息 2014-09-28 16:28:04 +08:00
guanghongwei
86b8124bec 修改 “修改用户”的一出bug 2014-09-28 12:03:59 +08:00
guanghongwei
c588aaea3a 添加修改用户信息 2014-09-28 11:57:20 +08:00
guanghongwei
52e567b157 修改授权问题 2014-09-27 20:58:50 +08:00
guanghongwei
5fd15478a8 修改vies 2014-09-27 20:20:45 +08:00
guanghongwei
5ccffe6c1d 添加install 2014-09-27 20:16:10 +08:00
guanghongwei
7d32a9a9e9 修改login 2014-09-27 19:44:46 +08:00
guanghongwei
0d5ff30acf 整理一遍 2014-09-27 19:26:33 +08:00
guanghongwei
a68454f7a4 修改 删除用户权限 2014-09-24 15:42:44 +08:00
guanghongwei
d4f40feebf 修改bug 2014-09-23 21:56:59 +08:00
guanghongwei
a25b2df453 修改一个bug 2014-09-23 21:49:22 +08:00
guanghongwei
a6f53fc99d 修改 登录和删除 2014-09-23 21:41:36 +08:00
guanghongwei
35e74f3c10 修改删除用户 2014-09-23 14:27:51 +08:00
guanghongwei
1ea85c3b19 更改显示 2014-09-18 19:42:09 +08:00
guanghongwei
8756172b9b 修改添加的类型 2014-09-18 15:53:43 +08:00
guanghongwei
d4ef81edc6 修改用户添加流程,抛弃shell操作 2014-09-18 14:39:00 +08:00
guanghongwei
0f18e702e8 修改保存 2014-09-16 18:23:56 +08:00
guanghongwei
63cdef4218 修改添加用户 2014-09-16 17:26:49 +08:00
guanghongwei
8596bc4997 修改adduser function 2014-09-16 16:58:09 +08:00
guanghongwei
e72aba98e6 修改单词拼写 2014-09-16 16:23:30 +08:00
guanghongwei
8b13967570 修改views的form引用 2014-09-16 16:22:00 +08:00
guanghongwei
0d842fe3ec 修改bug 2014-09-16 16:18:00 +08:00
guanghongwei
73d61e09ed 添加forms 2014-09-16 16:14:14 +08:00
guanghongwei
45b874fcd8 修改models顺序 2014-09-16 12:14:33 +08:00
guanghongwei
538b8c8a35 修改model表结构 2014-09-16 12:11:44 +08:00
guanghongwei
78d7255190 delete vpn comment 2014-09-16 10:35:51 +08:00
guanghongwei
07ee63f04c 删除runcommand目录 2014-09-15 21:19:07 +08:00
75 changed files with 3377 additions and 958 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.idea
*.pyc
*.log

View File

@@ -1,36 +1,39 @@
开源运维堡垒机(跳板机)系统
==============================
Jumpserver是什么
-----------------
Jumpserver是用Python+Django写的一个开源的跳板机(堡垒机)项目,来集中管理服务器的账号、密码和权限。
介绍和文档:
--------------
介绍和部署: [我的博客](http://laoguang.blog.51cto.com/6013350/1540080)
1.1版本更新
-----------------
更新Log见笔者blog<br>
http://laoguang.blog.51cto.com/6013350/1576502
部署文档
-----------------
部署文档见笔者blog<br>
http://laoguang.blog.51cto.com/6013350/1576729
截图
-------------
![登录](https://github.com/ibuler/static/blob/master/jumpserver/1.png)
![界面](https://github.com/ibuler/static/blob/master/jumpserver/web1.png)
![界面2](https://github.com/ibuler/static/blob/master/jumpserver/web2.png)
![界面3](https://github.com/ibuler/static/blob/master/jumpserver/web3.png)
![添加用户](https://github.com/ibuler/static/blob/master/jumpserver/2.png)
![添加host](https://github.com/ibuler/static/blob/master/jumpserver/add_host.png)
![添加权限](https://github.com/ibuler/static/blob/master/jumpserver/addperm.png)
![跳板机](https://github.com/ibuler/static/blob/master/jumpserver/view1.png)
![跳板机1](https://github.com/ibuler/static/blob/master/jumpserver/view2.png)
![跳板机2](https://github.com/ibuler/static/blob/master/jumpserver/view3.png)
![跳板机3](https://github.com/ibuler/static/blob/master/jumpserver/view4.png)
![跳板机4](https://github.com/ibuler/static/blob/master/jumpserver/view5.png)
![跳板机6](https://github.com/ibuler/static/blob/master/jumpserver/view6.png)
功能截图
-----------------
1. 安装<br>
![install](https://github.com/ibuler/static/blob/master/jumpserver1.1/1.%20install.png)
2. 登陆<br>
![login](https://github.com/ibuler/static/blob/master/jumpserver1.1/2.login.png)
3. 添加组<br>
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/3.addgroup.png)
4. 添加用户<br>![adduser](https://github.com/ibuler/static/blob/master/jumpserver1.1/5.adduser.png)
5. 添加主机<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/9.addhost.png)
6. 添加权限<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/11.addperm.png)
7. 查看权限<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/13.showperm.png)
8. 下载私钥<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/16.downkey.png)
9. 登陆shell<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/17.loginshell.png)
10. 显示有权限的主机<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/18.p.png)
11. 批量执行命令<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/19.e.png)
12. 登陆有权限的主机<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/20.%20loginserver.png)
13. 查看sudo<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/22.showsudo.png)
14. 修改sudo<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/25.addsudohost.png)
15. 查看实时监控<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/29.monitor1ok.png)
16. 结束会话<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/28.%20killsession.png)
17. 查看统计日志<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/30.viewlog2.png)
18. 修改密码<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/34.modpass.png)
19. 下载文件<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/32.downfile.png)
20. 上传文件<br>![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/30.upfile.png)

View File

@@ -1,21 +0,0 @@
#!/bin/bash
username=$1
password=$2
cwd (){
dir=$0
dirname $dir
}
dir=$(cwd)
. ${dir}/shell.conf
id ${username} &> /dev/null
if [ $? != 0 ];then
echo "$username is not exist."
exit 3
fi
echo "$password" | passwd --stdin "$username"
#ssh -p $host2_port $host2 "echo \"$password\" | passwd --stdin \"$username\""

View File

@@ -1,37 +0,0 @@
#!/bin/bash
user=$1
password=$2
cwd (){
dir=$0
dirname $dir
}
dir=$(cwd)
. ${dir}/shell.conf
keyfile=${dir}/keys/${user}
rm -f ${keyfile}
gen_key() {
ssh-keygen -t rsa -f ${keyfile} -P $1
}
if [ -z $1 ] || [ -z $2 ];then
echo "Usage: ./script user password"
exit 3
fi
gen_key ${password}
mkdir -p /home/${user}/.ssh
#ssh -p ${host2_port} ${host2} "mkdir -p /home/$user/.ssh"
cat ${keyfile}.pub > /home/${user}/.ssh/authorized_keys
#ssh -p ${host2_port} ${host2} "cat > /home/$user/.ssh/authorized_keys" < ${keyfile}.pub
chmod 600 /home/${user}/.ssh/authorized_keys
#ssh -p ${host2_port} ${host2} "chmod 600 /home/$user/.ssh/authorized_keys"
chown -R ${user}:${user} /home/${user}/.ssh
#ssh -p ${host2_port} ${host2} "chown -R $user:$user /home/$user/.ssh"

View File

@@ -8,14 +8,9 @@ password = redhat
db = jumpserver
[jumpserver]
log_dir = /opt/jumpserver/logs/
user_table = UserManage_user
assets_table = Assets_assets
assets_user_table = Assets_assetsuser
key = 88aaaf7ffe3c6c04
useradd_shell = /opt/jumpserver/useradd.sh
userdel_shell = /opt/jumpserver/userdel.sh
sudoadd_shell = /opt/jumpserver/sudoadd.sh
sudodel_shell = /opt/jumpserver/sudodel.sh
keygen_shell = /opt/jumpserver/genkey.sh
chgpass_shell = /opt/jumpserver/chgpass.sh
ldap_host = ldap://127.0.0.1:389
ldap_base_dn = dc=yolu,dc=com
admin_cn = cn=admin,dc=yolu,dc=com
admin_pass = VNLqNCjpNBIetEoCA2h3
web_socket_host = 172.10.10.9:3000

View File

@@ -1,11 +1,10 @@
#!/usr/bin/python
# coding: utf-8
import os
import sys
import subprocess
import MySQLdb
import pexpect
import struct
import fcntl
import termios
@@ -16,20 +15,28 @@ from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import ConfigParser
import paramiko
import pxssh
import pexpect
cur_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.append('%s/webroot/AutoSa/' % cur_dir)
os.environ['DJANGO_SETTINGS_MODULE'] = 'AutoSa.settings'
import django
django.setup()
from UserManage.models import User, Logs, Pid
from Assets.models import Assets
base_dir = "/opt/jumpserver/"
cf = ConfigParser.ConfigParser()
cf.read('%s/jumpserver.conf' % base_dir)
cf.read('%s/jumpserver.conf' % cur_dir)
db_host = cf.get('db', 'host')
db_port = cf.getint('db', 'port')
db_user = cf.get('db', 'user')
db_password = cf.get('db', 'password')
db_db = cf.get('db', 'db')
log_dir = cf.get('jumpserver', 'log_dir')
user_table = cf.get('jumpserver', 'user_table')
assets_table = cf.get('jumpserver', 'assets_table')
assets_user_table = cf.get('jumpserver', 'assets_user_table')
log_dir = os.path.join(cur_dir, 'logs')
key = cf.get('jumpserver', 'key')
@@ -61,7 +68,10 @@ class PyCrypt(object):
def sigwinch_passthrough(sig, data):
"""This function use to set the window size of the terminal!"""
winsize = getwinsize()
foo.setwinsize(winsize[0], winsize[1])
try:
foo.setwinsize(winsize[0], winsize[1])
except:
pass
def getwinsize():
@@ -69,24 +79,12 @@ def getwinsize():
if 'TIOCGWINSZ' in dir(termios):
TIOCGWINSZ = termios.TIOCGWINSZ
else:
TIOCGWINSZ = 1074295912L # Assume
TIOCGWINSZ = 1074295912L # Assume
s = struct.pack('HHHH', 0, 0, 0, 0)
x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
return struct.unpack('HHHH', x)[0:2]
def connect_db(user, passwd, db, host='127.0.0.1', port=3306):
"""This function connect db and return db and cursor"""
db = MySQLdb.connect(host=host,
port=port,
user=user,
passwd=passwd,
db=db,
charset='utf8')
cursor = db.cursor()
return db, cursor
def run_cmd(cmd):
"""run command and return stdout"""
pipe = subprocess.Popen(cmd,
@@ -105,79 +103,75 @@ def run_cmd(cmd):
def connect(host, port, user, password):
"""Use pexpect module to connect other server."""
if not os.path.isdir(log_dir):
os.mkdir(log_dir)
logfile = open("%s/%s_%s_%s" % (log_dir, host, time.strftime('%Y%m%d'), user), 'a')
logfile.write('\n\n%s\n\n' % time.strftime('%Y%m%d_%H%M%S'))
cmd = 'ssh -p %s %s@%s' % (port, user, host)
global foo
foo = pexpect.spawn('/bin/bash', ['-c', cmd])
foo.logfile = logfile
while True:
index = foo.expect(['continue',
'assword',
pexpect.EOF,
pexpect.TIMEOUT], timeout=3)
if index == 0:
foo.sendline('yes')
continue
elif index == 1:
foo.sendline(password)
log_date_dir = '%s/%s' % (log_dir, time.strftime('%Y%m%d'))
if not os.path.isdir(log_date_dir):
os.mkdir(log_date_dir)
os.chmod(log_date_dir, 0777)
structtime_start = time.localtime()
datetime_start = time.strftime('%Y%m%d%H%M%S', structtime_start)
logtime_start = time.strftime('%Y/%m/%d %H:%M:%S', structtime_start)
timestamp_start = int(time.mktime(structtime_start))
logfile_name = "%s/%s_%s_%s" % (log_date_dir, host, user, datetime_start)
index = foo.expect(['assword',
'.*',
pexpect.EOF,
pexpect.TIMEOUT], timeout=3)
if index == 1:
signal.signal(signal.SIGWINCH, sigwinch_passthrough)
size = getwinsize()
foo.setwinsize(size[0], size[1])
print "\033[32;1mLogin %s success!\033[0m" % host
foo.interact()
break
elif index == 0:
print "Password error."
break
else:
print "Login failed, please contact system administrator!"
break
foo.terminate(force=True)
try:
global foo
foo = pxssh.pxssh()
foo.login(host, user, password, port=port, auto_prompt_reset=False)
log = Logs(user=user, host=host, logfile=logfile_name, start_time=timestamp_start, ppid=os.getpid()) # 日志信息记录到数据库
log.save()
pid = Pid(ppid=os.getpid(), cpid=foo.pid, start_time=timestamp_start, logid=log.id)
pid.save()
logfile = open(logfile_name, 'a') # 记录日志文件
logfile.write('\nDateTime:%s' % logtime_start)
foo.logfile = logfile
foo.sendline('')
signal.signal(signal.SIGWINCH, sigwinch_passthrough)
size = getwinsize()
foo.setwinsize(size[0], size[1])
foo.interact(escape_character=chr(28)) # 进入交互模式
logfile.write('\nEndTime: %s' % time.strftime('%Y/%m/%d %H:%M:%S'))
log.finish = 1
log.end_time = int(time.time())
log.save()
except pxssh.ExceptionPxssh as e:
print('登录失败: %s' % e)
except pexpect.EOF:
print('登录失败: Host refuse')
except KeyboardInterrupt:
foo.logout()
log.finish = 1
log.end_time = int(time.time())
log.save()
def ip_all_select(username):
"""select all the server of the user can control."""
ip_all = []
ip_all_dict = {}
db, cursor = connect_db(db_user, db_password, db_db, db_host, db_port)
cursor.execute('select t2.ip, t2.comment from %s t1, %s t2, %s t3 where t1.username="%s" and t1.id=t3.uid_id and t2.id = t3.aid_id;' %
(user_table, assets_table, assets_user_table, username))
ip_all_record = cursor.fetchall()
if ip_all_record:
for record in ip_all_record:
ip_all.append(record[0])
ip_all_dict[record[0]] = record[1]
db.close()
try:
user = User.objects.get(username=username)
except:
return (['error'], {'error':"Don't Use Root To Do That or User isn't Exist."})
all_assets_user = user.assetsuser_set.all()
for assets_user in all_assets_user:
ip_all.append(assets_user.aid.ip)
ip_all_dict[assets_user.aid.ip] = assets_user.aid.comment
return ip_all, ip_all_dict
def sth_select(username='', ip=''):
"""if username: return password elif ip return port"""
db, cursor = connect_db(db_user, db_password, db_db, db_host, db_port)
if username:
cursor.execute('select password from %s where username="%s"' % (user_table, username))
try:
password = cursor.fetchone()[0]
except IndexError:
password = ''
db.close()
return password
user = User.objects.get(username=username)
ldap_password = user.ldap_password
return ldap_password
if ip:
cursor.execute('select port from %s where ip="%s"' % (assets_table, ip))
try:
port = int(cursor.fetchone()[0])
except IndexError:
port = 22
db.close()
asset = Assets.objects.get(ip=ip)
port = asset.port
return port
return None
@@ -247,31 +241,45 @@ def exec_cmd_servers(username):
ip_all, ip_all_dict = ip_all_select(username)
no_perm = set(hosts)-set(ip_all)
if no_perm:
print "You have no permission on %s." % list(no_perm)
print "You have NO PERMISSION on %s..." % list(no_perm)
continue
print '\nInput the \033[32mCommand\033[0m , The command will be Execute on servers, q/Q to quit.\n'
while True:
cmd = raw_input('\033[1;32mCmd(s): \033[0m')
if cmd in ['q', 'Q']:
break
exec_log_dir = os.path.join(log_dir, 'exec_cmds')
if not os.path.isdir(exec_log_dir):
os.mkdir(exec_log_dir)
os.chmod(exec_log_dir, 0777)
filename = "%s/%s.log" % (exec_log_dir, time.strftime('%Y%m%d'))
f = open(filename, 'a')
f.write("DateTime: %s User: %s Host: %s Cmds: %s\n" %
(time.strftime('%Y/%m/%d %H:%M:%S'), username, hosts, cmd))
for host in hosts:
remote_exec_cmd(host, username, cmd)
def connect_one(username, option):
ip = option.strip()
ip_input = option.strip()
ip_all, ip_all_dict = ip_all_select(username)
ip_matched = match_ip(ip_all, ip)
ip_matched = match_ip(ip_all, ip_input)
ip_len = len(ip_matched)
if ip_len == 1:
ip = ip_matched[0]
password = jm.decrypt(sth_select(username=username))
port = sth_select(ip=ip)
print "Connecting %s ..." % ip
connect(ip, port, username, password)
elif ip_len > 1:
for ip in ip_matched:
print ip
ip = ''
if ip_len >= 1:
if ip_len == 1:
ip = ip_matched[0]
else:
if ip_input in ip_matched:
ip = ip_input
else:
for one_ip in ip_matched:
print one_ip
if ip:
password = jm.decrypt(sth_select(username=username))
port = sth_select(ip=ip)
print "Connecting %s ..." % ip
connect(ip, port, username, password)
else:
print '\033[31mNo permision .\033[0m'
@@ -282,7 +290,11 @@ if __name__ == '__main__':
print_prompt()
try:
while True:
option = raw_input("\033[1;32mOpt or IP>:\033[0m ")
try:
option = raw_input("\033[1;32mOpt or IP>:\033[0m ")
except EOFError:
print
continue
if option in ['P', 'p']:
print_your_server(username)
continue
@@ -292,7 +304,7 @@ if __name__ == '__main__':
sys.exit()
else:
connect_one(username, option)
except (BaseException, Exception):
#except IndexError:
#except (BaseException, Exception):
except IndexError:
print "Exit."
sys.exit()

18
runserver Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
manage_file="./webroot/AutoSa/manage.py"
log_handler_file="./webroot/AutoSa/log_handler.py"
websocket_file="./webroot/AutoSa/websocket/index.js"
which node &> /dev/null
if [ $? != '0' ];then
echo "Please define the node.js binary file 'node' in the PATH."
exit
fi
node $websocket_file &
if [ -f $manage_file -a -e $manage_file ] && [ -f $log_handler_file -a -e $log_handler_file ];then
$manage_file runserver 0.0.0.0:80 &> logs/access.log &
$log_handler_file &> logs/handler.log &
else
echo "manage.py or log_handler.py isn't exist or executable."
fi

4
jumpserver.sh → scripts/jumpserver.sh Executable file → Normal file
View File

@@ -1,6 +1,6 @@
#!/bin/bash
if [ $USER = 'admin' ] || [ $USER == 'root' ];then
if [ $USER == 'admin' ] || [ $USER == 'root' ];then
echo ""
else
python /opt/jumpserver/jumpserver.py
@@ -10,4 +10,4 @@ else
exit 3
echo
fi
fi
fi

8
scripts/requirements.txt Normal file
View File

@@ -0,0 +1,8 @@
pexpect==3.3
sphinx-me==0.3
django==1.7.1
python-ldap==2.4.18
paramiko==1.15.1
pycrypto==2.6.1
ecdsa>=0.11
MySQL-python==1.2.5

View File

@@ -1,8 +0,0 @@
#!/bin/bash
host=127.0.0.1
ldapassword=VNLqNCjpNBIetEoCA2h3
domain=dianping
suffix=com
#host2=172.16.2.74
#host2_port=2001

5
stopserver Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
pids=$(ps axu | grep -E '(manage.py|log_handler|index.js)' | grep -v 'grep' | awk '{ print $2 }')
for pid in $pids;do
kill -15 $pid
done

View File

@@ -1,9 +0,0 @@
dn: cn=guanghongwei,ou=Sudoers,dc=dianping,dc=com
objectClass: top
objectClass: sudoRole
cn: guanghongwei
sudoCommand: /bin/pwd
sudoHost: ALL
sudoOption: !authenticate
sudoRunAsUser: ALL
sudoUser: guanghongwei

View File

@@ -1,36 +0,0 @@
#!/bin/bash
username=$1
password=$2
cwd (){
dir=$0
dirname $dir
}
dir=$(cwd)
. ${dir}/shell.conf
sudo_file=${dir}/sudo.ldif
user_sudo_file=${dir}/${username}.ldif
if [ -z $1 ];then
echo
echo "usage: ./sudoadd.sh username "
echo
exit 3
fi
id ${username} &> /dev/null
if [ $? != '0' ];then
echo "$username is not exit!"
exit 3
fi
sed -i "/guanghongwei/ s@dianping@$domain@g" ${sudo_file}
sed -i "/guanghongwei/ s@com@$suffix@g" ${sudo_file}
sed -e "s@guanghongwei@$username@g" ${sudo_file} > $user_sudo_file
ldapadd -x -h ${host} -w ${ldapassword} -D "cn=admin,dc=$domain,dc=$suffix" -f $user_sudo_file
rm -f $user_sudo_file

View File

@@ -1,18 +0,0 @@
#!/bin/bash
username=$1
password=$2
cwd (){
dir=$0
dirname $dir
}
dir=$(cwd)
. ${dir}/shell.conf
id $username &> /dev/null
if [ $? == '0' ];then
userdel -r $username
else
echo "$username is not exist."
fi
ldapdelete -x -h $host -D "cn=admin,dc=$domain,dc=$suffix" -w $ldapassword "cn=$username,ou=Sudoers,dc=$domain,dc=$suffix"

View File

@@ -1,38 +0,0 @@
#!/bin/bash
username=$1
password=$2
cwd (){
dir=$0
dirname $dir
}
dir=$(cwd)
. ${dir}/shell.conf
if [ -z $1 ] || [ -z $2 ];then
echo
echo "usage: ./useradd.sh username password"
echo
exit 3
fi
id $username &> /dev/null
if [ $? != '0' ];then
useradd $username
#ssh -p $host2_port $host2 "useradd $username"
echo $password | passwd --stdin $username
else
echo "$username have been exits."
exit 5
fi
cd /usr/share/migrationtools/
./migrate_passwd.pl /etc/passwd > /tmp/passwd.ldif
./migrate_group.pl /etc/group > /tmp/group.ldif
grep -A15 "dn: uid=$username,ou=People,dc=$domain,dc=$suffix" /tmp/passwd.ldif > /tmp/user.ldif
grep -A6 "dn: cn=$username,ou=Group,dc=$domain,dc=$suffix" /tmp/group.ldif > /tmp/usergroup.ldif
ldapadd -x -h $host -w $ldapassword -D "cn=admin,dc=$domain,dc=$suffix" -f /tmp/user.ldif
ldapadd -x -h $host -w $ldapassword -D "cn=admin,dc=$domain,dc=$suffix" -f /tmp/usergroup.ldif

View File

@@ -1,21 +0,0 @@
#!/bin/bash
username=$1
password=$2
cwd (){
dir=$0
dirname $dir
}
dir=$(cwd)
. ${dir}/shell.conf
id $username &> /dev/null
if [ $? == '0' ];then
userdel -r $username
#ssh -p $host2_port $host2 "userdel -r $username"
else
echo "$username is not exist."
fi
ldapdelete -x -h $host -D "cn=admin,dc=$domain,dc=$suffix" -w $ldapassword "uid=$username,ou=People,dc=$domain,dc=$suffix"
ldapdelete -x -h $host -D "cn=admin,dc=$domain,dc=$suffix" -w $ldapassword "cn=$username,ou=Group,dc=$domain,dc=$suffix"

Binary file not shown.

View File

@@ -2,10 +2,18 @@ from django.db import models
from UserManage.models import User
class IDC(models.Model):
name = models.CharField(max_length=20)
def __unicode__(self):
return self.name
class Assets(models.Model):
id = models.AutoField(primary_key=True)
ip = models.CharField(max_length=20)
port = models.IntegerField(max_length=5)
idc = models.ForeignKey(IDC)
comment = models.CharField(max_length=100, blank=True, null=True)
def __unicode__(self):
@@ -14,4 +22,6 @@ class Assets(models.Model):
class AssetsUser(models.Model):
uid = models.ForeignKey(User)
aid = models.ForeignKey(Assets)
aid = models.ForeignKey(Assets)

Binary file not shown.

Binary file not shown.

View File

@@ -12,16 +12,16 @@ https://docs.djangoproject.com/en/1.6/ref/settings/
import os
import ConfigParser
base_dir = "/opt/jumpserver/"
cf = ConfigParser.ConfigParser()
cf.read('%s/jumpserver.conf' % base_dir)
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
CONF_DIR = os.path.dirname(os.path.dirname(BASE_DIR))
CF = ConfigParser.ConfigParser()
CF.read('%s/jumpserver.conf' % CONF_DIR)
db_host = cf.get('db', 'host')
db_port = cf.getint('db', 'port')
db_user = cf.get('db', 'user')
db_password = cf.get('db', 'password')
db_db = cf.get('db', 'db')
DB_HOST = CF.get('db', 'host')
DB_PORT = CF.getint('db', 'port')
DB_USER = CF.get('db', 'user')
DB_PASSWORD = CF.get('db', 'password')
DB_DB = CF.get('db', 'db')
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/
@@ -48,6 +48,7 @@ INSTALLED_APPS = (
'django.contrib.staticfiles',
'UserManage',
'Assets',
'AutoSa',
#'RunCommand',
)
@@ -71,11 +72,11 @@ WSGI_APPLICATION = 'AutoSa.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': db_db,
'USER': db_user,
'PASSWORD': db_password,
'HOST': db_host,
'PORT': db_port,
'NAME': DB_DB,
'USER': DB_USER,
'PASSWORD': DB_PASSWORD,
'HOST': DB_HOST,
'PORT': DB_PORT,
}
}

Binary file not shown.

View File

@@ -0,0 +1,12 @@
import time
from django import template
register = template.Library()
@register.filter(name='stamp2str')
def stamp2str(value):
try:
return time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(value))
except AttributeError:
return '0000/00/00 00:00:00'

View File

@@ -10,11 +10,21 @@ urlpatterns = patterns('',
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
(r'^install/', views.install),
(r'^$', views.index),
(r'^login/$', views.login),
(r'^logout/$', views.logout),
(r'^showUser/$', views.showUser),
(r'^addUser/$', views.addUser),
(r'^chgUser/$', views.chgUser),
(r'^showGroup/$', views.showGroup),
(r'^addGroup/$', views.addGroup),
(r'^chgGroup/$', views.chgGroup),
(r'^showIDC/$', views.showIDC),
(r'^addIDC/$', views.addIDC),
(r'^chgIDC/$', views.chgIDC),
(r'^showSudo/$', views.showSudo),
(r'^chgSudo/$', views.chgSudo),
(r'^showAssets/$', views.showAssets),
(r'^addAssets/$', views.addAssets),
(r'^showPerm/$', views.showPerm),
@@ -22,4 +32,9 @@ urlpatterns = patterns('',
(r'^downKey/$', views.downKey),
(r'^chgPass/$', views.chgPass),
(r'^chgKey/$', views.chgKey),
(r'^upFile/$', views.upFile),
(r'^downFile/$', views.downFile),
(r'^logView/$', views.logView),
(r'^logHistory/$', views.logHistory),
(r'^killSession/$', views.killSession),
)

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@@ -1,12 +0,0 @@
from django.db import models
class Server(models.Model):
ip = models.CharField(max_length=16)
username = models.CharField(max_length=20)
password = models.CharField(max_length=30)
port = models.IntegerField(max_length=5)
sudo = models.BooleanField()
def __unicode__(self):
return self.ip

View File

@@ -1,2 +0,0 @@
from django.shortcuts import render

View File

@@ -0,0 +1,48 @@
# coding: utf-8
from django import forms
from UserManage.models import Group
class GroupAddForm(forms.Form):
name = forms.CharField(max_length=30)
class UserAddForm(forms.Form):
username = forms.CharField(max_length=30,
widget=forms.TextInput(
attrs={'class': 'form-control', 'placeholder': '用户名'}))
password = forms.CharField(max_length=30,
widget=forms.PasswordInput(
attrs={'class': 'form-control', 'placeholder': '密码'}))
password_again = forms.CharField(max_length=30,
widget=forms.PasswordInput(
attrs={'class': 'form-control', 'placeholder': '确认密码'}))
key_pass = forms.CharField(max_length=30, min_length=6,
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '密钥密码'}))
key_pass_again = forms.CharField(max_length=30,
widget=forms.PasswordInput(
attrs={'class': 'form-control', 'placeholder': '确认密码'}))
name = forms.CharField(max_length=30,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '姓名'}))
group = forms.ModelMultipleChoiceField(queryset=Group.objects.all(),
widget=forms.SelectMultiple(attrs={'class': 'form-control'}))
is_admin = forms.BooleanField(required=False)
is_superuser = forms.BooleanField(required=False)
def clean_password_again(self):
password = self.cleaned_data['password']
password_again = self.cleaned_data['password_again']
if password != password_again:
raise forms.ValidationError(u'密码二次输入不一致. ')
return password_again
def clean_key_pass_again(self):
key_pass = self.data['key_pass']
key_pass_again = self.data['key_pass_again']
if key_pass != key_pass_again:
raise forms.ValidationError(u'密码二次输入不一致. ')
if len(key_pass) < 6:
raise forms.ValidationError(u'密码二次输入不一致. ')
return key_pass_again

View File

@@ -1,11 +1,48 @@
from django.db import models
class User(models.Model):
username = models.CharField(max_length=50)
password = models.CharField(max_length=100)
name = models.CharField(max_length=50)
email = models.EmailField(max_length=50)
class Group(models.Model):
name = models.CharField(max_length=50, unique=True)
def __unicode__(self):
return self.username
return self.name
class User(models.Model):
username = models.CharField(max_length=50, unique=True)
password = models.CharField(max_length=100)
key_pass = models.CharField(max_length=100)
name = models.CharField(max_length=50)
group = models.ManyToManyField(Group)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
ldap_password = models.CharField(max_length=100, null=False)
email = models.EmailField(max_length=50, null=True, blank=True)
def __unicode__(self):
return self.username
class Logs(models.Model):
user = models.CharField(max_length=50)
host = models.CharField(max_length=20)
logfile = models.CharField(max_length=1000)
finish = models.SmallIntegerField(max_length=4, default=0)
ppid = models.IntegerField()
start_time = models.IntegerField()
end_time = models.IntegerField(default=0)
def __unicode__(self):
return self.logfile
class Pid(models.Model):
"""
ppid : parent pid
cpid: child pid
"""
ppid = models.IntegerField()
cpid = models.IntegerField()
logid = models.IntegerField()
start_time = models.IntegerField()

Binary file not shown.

96
webroot/AutoSa/log_handler.py Executable file
View File

@@ -0,0 +1,96 @@
#!/usr/bin/python
#coding: utf-8
import os
import sys
import time
cur_dir = os.path.dirname(__file__)
sys.path.append('%s/webroot/AutoSa/' % cur_dir)
os.environ['DJANGO_SETTINGS_MODULE'] = 'AutoSa.settings'
import django
django.setup()
from UserManage.models import Logs, Pid
def log_hanler(logid):
log = Logs.objects.filter(id=logid)
if log:
log = log[0]
filename = log.logfile
if os.path.isfile(filename):
ret1 = os.system('cat %s | grep "DateTime" > %s.his' % (filename, filename))
ret2 = os.system('cat %s | grep "\[.*@.*\][\$\#]" >> %s.his' % (filename, filename))
ret3 = os.system('cat %s | grep "EndTime" >> %s.his' % (filename, filename))
if (ret1 + ret2 + ret3) == 0:
print 'Handler %s ok.' % filename
def set_finish(id):
logs = Logs.objects.filter(id=id, finish=0)
if logs:
structtime_start = time.localtime()
timestamp_end = int(time.mktime(structtime_start))
log = logs[0]
log.finish = 1
log.end_time = timestamp_end
log.save()
def kill_pid(pid):
try:
os.kill(pid, 9)
except OSError:
pass
def pid_exist(pid):
pid_dir = "/proc/%s" % pid
if os.path.isdir(pid_dir):
return True
else:
return False
def del_pid(pid_id):
pid = Pid.objects.filter(id=pid_id)
if pid:
pid[0].delete()
def get_pids():
pids = []
pids_obj = Pid.objects.all()
for pid_obj in pids_obj:
pids.append((pid_obj.id, pid_obj.ppid, pid_obj.cpid, pid_obj.logid, pid_obj.start_time))
return pids
def run():
for pid_id, ppid, cpid, logid, start_time in get_pids():
if pid_exist(cpid):
if pid_exist(ppid):
structtime_start = time.localtime()
timestamp_end = int(time.mktime(structtime_start))
if timestamp_end - start_time > 7200:
kill_pid(ppid)
kill_pid(cpid)
del_pid(pid_id)
set_finish(logid)
log_hanler(logid)
else:
kill_pid(cpid)
del_pid(pid_id)
set_finish(logid)
log_hanler(logid)
else:
del_pid(pid_id)
set_finish(logid)
log_hanler(logid)
if __name__ == '__main__':
while True:
run()
time.sleep(0.5)

View File

@@ -1,3 +0,0 @@
#!/bin/bash
./manage.py runserver 0.0.0.0:80

View File

@@ -0,0 +1,120 @@
.bootstrap-dialog {
}
.bootstrap-dialog .modal-header {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.bootstrap-dialog .bootstrap-dialog-title {
color: #fff;
display: inline-block;
}
.bootstrap-dialog.type-default .bootstrap-dialog-title {
color: #333;
}
.bootstrap-dialog.size-normal .bootstrap-dialog-title {
font-size: 16px;
}
.bootstrap-dialog.size-large .bootstrap-dialog-title {
font-size: 24px;
}
.bootstrap-dialog .bootstrap-dialog-close-button {
float: right;
filter:alpha(opacity=90);
-moz-opacity:0.9;
-khtml-opacity: 0.9;
opacity: 0.9;
}
.bootstrap-dialog.size-normal .bootstrap-dialog-close-button {
font-size: 20px;
}
.bootstrap-dialog.size-large .bootstrap-dialog-close-button {
font-size: 30px;
}
.bootstrap-dialog .bootstrap-dialog-close-button:hover {
cursor: pointer;
filter: alpha(opacity=100);
-moz-opacity: 1;
-khtml-opacity: 1;
opacity: 1;
}
.bootstrap-dialog.size-normal .bootstrap-dialog-message {
font-size: 14px;
}
.bootstrap-dialog.size-large .bootstrap-dialog-message {
font-size: 18px;
}
.bootstrap-dialog.type-default .modal-header {
background-color: #fff;
}
.bootstrap-dialog.type-info .modal-header {
background-color: #5bc0de;
}
.bootstrap-dialog.type-primary .modal-header {
background-color: #428bca;
}
.bootstrap-dialog.type-success .modal-header {
background-color: #5cb85c;
}
.bootstrap-dialog.type-warning .modal-header {
background-color: #f0ad4e;
}
.bootstrap-dialog.type-danger .modal-header {
background-color: #d9534f;
}
.bootstrap-dialog .bootstrap-dialog-button-icon {
margin-right: 3px;
}
/**
* Icon animation
* Copied from font-awesome: http://fontawesome.io/
**/
.icon-spin {
display: inline-block;
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
-webkit-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
}
@-moz-keyframes spin {
0% {
-moz-transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
}
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
}
}
@-o-keyframes spin {
0% {
-o-transform: rotate(0deg);
}
100% {
-o-transform: rotate(359deg);
}
}
@-ms-keyframes spin {
0% {
-ms-transform: rotate(0deg);
}
100% {
-ms-transform: rotate(359deg);
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}
}
/** End of icon animation **/

File diff suppressed because it is too large Load Diff

View File

@@ -12,4 +12,6 @@ function selectAll(){
checklist[j].checked = 0;
}
}
}

View File

@@ -25,10 +25,25 @@
<input type="text" class="form-control" id="port" name="port" placeholder="Port">
</div>
</div>
<div class="form-group">
<label for="idc" class="col-sm-2 control-label">IDC<span style="color: red"> *</span></label>
<div class="col-sm-4">
<select name="idc" id="idc" class="form-control">
{% for idc in idcs %}
<option value="{{ idc.id }}">{{ idc.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-sm-4">
<a href="/addIDC/">添加IDC</a>
<a href="/showIDC/">删除IDC</a>
</div>
</div>
<div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注<span style="color: red"></span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="comment" name="comment" placeholder="备注">
<input type="text" class="form-control" id="comment" name="comment" placeholder="备注(最好是英文)">
</div>
</div>

View File

@@ -0,0 +1,30 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" role="form" method="post" action="" >
<fieldset >
<legend>添加属组</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<label for="name" class="col-sm-2 control-label">属组<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="name" name="name" placeholder="属组">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">添加</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}

View File

@@ -0,0 +1,31 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" role="form" method="post" action="" >
<fieldset >
<legend>添加IDC</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<label for="name" class="col-sm-2 control-label">IDC<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="name" name="name" placeholder="IDC">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">添加</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}

View File

@@ -1,41 +0,0 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" role="form" method="post" action="" >
<fieldset >
<legend>添加OpenVPN用户</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="username" name="username" placeholder="用户名">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
</div>
</div>
<div class="form-group">
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">确认添加</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}

View File

@@ -26,7 +26,7 @@
{% endfor %}
</tbody>
</table>
<button class="btn btn-primary">删除</button></td>
<button class="btn btn-success">删除</button></td>
</form>
{% endblock %} %}

View File

@@ -1,56 +0,0 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" role="form" method="post" action="" >
<fieldset >
<legend>添加执行命令主机</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<label for="pub_ip" class="col-sm-2 control-label">IP<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="pub_ip" name="pub_ip" placeholder="IP">
</div>
</div>
<div class="form-group">
<label for="username" class="col-sm-2 control-label">账号<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="username" name="username" placeholder="账号">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
</div>
</div>
<div class="form-group">
<label for="port" class="col-sm-2 control-label">端口号<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="port" name="port" placeholder="端口号">
</div>
</div>
<div class="form-group">
<label for="sudo" class="col-sm-2 control-label">sudo<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="checkbox" style="margin-top: 12px;" id="sudo" name="sudo">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-sm btn-primary">添加</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}

View File

@@ -8,51 +8,85 @@
{{ error }}
</div>
{% endif %}
{% if form.errors %}
<div class="alert alert-danger">
Please correct the error{{ form.errors|pluralize }} below.
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
{{ form.username.errors }}
<label for="id_username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="username" name="username" placeholder="用户名">
{{ form.username }}
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
{{ form.password.errors }}
<label for="id_password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
{{ form.password }}
</div>
</div>
<div class="form-group">
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
{{ form.password_again.errors }}
<label for="id_password_again" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
{{ form.password_again }}
</div>
</div>
<div class="form-group">
<label for="keypass" class="col-sm-2 control-label">Key密码<span style="color: red"> *</span></label>
{{ form.key_pass.errors }}
<label for="id_keypass" class="col-sm-2 control-label">密钥密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="keypass" name="keypass" placeholder="Key密码">
{{ form.key_pass }}
</div>
</div>
<div class="form-group">
<label for="keypass_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
{{ form.key_pass_again.errors }}
<label for="id_keypass_again" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="keypass_confirm" name="keypass_confirm" placeholder="确认密码">
{{ form.key_pass_again }}
</div>
</div>
<div class="form-group">
<label for="name" class="col-sm-2 control-label">姓名<span style="color: red"> *</span></label>
{{ form.name.errors }}
<label for="id_name" class="col-sm-2 control-label">姓名<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="name" name='name' placeholder="姓名">
{{ form.name }}
</div>
</div>
<div class="form-group">
<label for="email" class="col-sm-2 control-label">E-mail</label>
{{ form.group.errors }}
<label for="id_group" class="col-sm-2 control-label">属组</label>
<div class="col-sm-4">
<input type="email" class="form-control" id="email" name="email" placeholder="用户名">
{{ form.group }}
</div>
<div class="col-sm-4">
<a href="/addGroup/">添加属组</a>
</div>
<div class="col-sm-4">
<a href="/showGroup/">删除属组</a>
</div>
</div>
<div class="form-group">
{{ form.is_admin.errors }}
<label for="id_is_admin" class="col-sm-2 control-label">组admin</label>
<div class="col-sm-4">
{{ form.is_admin }}
</div>
</div>
<div class="form-group">
{{ form.is_superuser.errors }}
<label for="id_is_superuser" class="col-sm-2 control-label">超级admin</label>
<div class="col-sm-4">
{{ form.is_superuser }}
</div>
</div>
<div class="form-group">

View File

@@ -1,3 +0,0 @@
{% extends 'base.html' %}
{% block content %}
{% endblock %}

View File

@@ -1,34 +0,0 @@
{% extends "base.html" %}
{% block content %}
<h2 class="text-center">修改主机信息</h2>
<form role="form" action="" method="post">
<div class="form-group has-success">
<label class="control-label" for="inputSuccess">编号</label>
<input type="text" class="form-control" id="inputSuccess" name="s_num" value='{{ post.s_num }}'>
<label class="control-label" for="inputSuccess">IP</label>
<input type="text" class="form-control" id="inputSuccess" name="s_ip" value='{{ post.s_ip }}'>
<label class="control-label" for="inputSuccess">主机名</label>
<input type="text" class="form-control" id="inputSuccess" name="s_hostname" value='{{ post.s_hostname }}'>
<label class="control-label" for="inputSuccess">CPU</label>
<input type="text" class="form-control" id="inputSuccess" name="s_cpu" value='{{ post.s_cpu }}'>
<label class="control-label" for="inputSuccess">内存</label>
<input type="text" class="form-control" id="inputSuccess" name="s_mem" value='{{ post.s_mem }}'>
<label class="control-label" for="inputSuccess">硬盘</label>
<input type="text" class="form-control" id="inputSuccess" name="s_disk" value='{{ post.s_disk }}'>
<label class="control-label" for="inputSuccess">操作系统</label>
<input type="text" class="form-control" id="inputSuccess" name="s_system" value='{{ post.s_system }}'>
<div class="form-group has-success">
<label class="control-label" for="inputSuccess">内核版本</label>
<input type="text" class="form-control" id="inputSuccess" name="s_kernel" value='{{ post.s_kernel }}'>
</div>
<button type="submit" class="btn btn-success col-sm-offset-5">提交更改</button>
</div>
</form>
{% endblock %}

View File

@@ -1,58 +0,0 @@
{% extends "base.html" %}
{% block content %}
<div>
<div style="float:left"><h2>主机列表</h2></div>
<div style="float:right;margin-top:16pt"><a href="/assets/add/" target="_black" class="btn btn-info">添加&nbsp;<i class="glyphicon glyphicon-plus-sign"></i></a></div>
</div>
<table class="table table-striped table-hover table-bordered" id="sample_editable_1">
<thead>
<tr>
<th class="text-center">编号</th>
<th class="text-center">IP</th>
<th class="text-center">主机名</th>
<th class="text-center">cpu</th>
<th class="text-center">内存</th>
<th class="text-center">硬盘</th>
<th class="text-center">操作系统</th>
<th class="text-center">详情</th>
<th class="text-center">编辑</th>
<th class="text-center">删除</th>
</tr>
</thead>
<tbody>
{% for post in contacts.object_list %}
<tr class="">
<td class="text-center">{{ post.s_num }}</td>
<td class="text-center">{{ post.s_ip }}</td>
<td class="text-center">{{ post.s_hostname }}</td>
<td class="text-center">{{ post.s_cpu }}</td>
<td class="text-center">{{ post.s_mem }}</td>
<td class="text-center">{{ post.s_disk }}</td>
<td class="text-center">{{ post.s_system }}</td>
<td class="text-center"><a href="/assets/show/{{ post.s_ip }}">详情</a></td>
<td class="text-center"><a href="/assets/edit/{{ post.s_ip }}">编辑</a></td>
<td class="text-center"><a href="/assets/delete/{{ post.s_ip }}">删除</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<ul class="pagination">
{% if contacts.has_previous %}
<li><a href="?page={{ contacts.previous_page_number }}">&laquo;</a></li>
{% endif %}
{% for page in p.page_range %}
{% ifequal offset1 page %}
<li class="active"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% else %}
<li><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% if contacts.has_next %}
<li><a href="?page={{ contacts.next_page_number }}">&raquo;</a></li>
{% endif %}
</ul>
{% endblock %}

View File

@@ -2,26 +2,31 @@
<html>
<head>
<meta charset="utf-8">
<title>运维管理系统</title>
<link rel="shortcut icon" type="image/x-icon" href="http://img.youlu.com/web/favicon.gif" />
<title>Jumpserver</title>
<link rel="shortcut icon" type="image/x-icon" href="" />
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5js"></script>
<![endif]-->
<link href="/static/css/bootstrap.css" rel="stylesheet">
<link href="/static/css/bootstrap-dialog.css" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet">
<script src="/static/js/main.js"></script>
<script src="/static/js/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="/static/js/bootstrap.min.js"></script>
<script src="/static/js/bootstrap-dialog.js"></script>
<script src="/static/js/main.js"></script>
</head>
<body>
{% if not admin %}
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="navbar-header"> <a class="navbar-brand" href="#">运维管理系统</a> </div>
<div class="navbar-header"> <a class="navbar-brand" href="#">Jumpserver</a> </div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="{{ index }}"><a href="/">主页</a></li>
@@ -47,18 +52,30 @@
<div class="row>
<!--Sidebar content-->
<div class="sidebar-menu">
<div class="menu-first" ><a href="#userMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 密码管理</a></div>
<div class="menu-first" ><a href="#userMenu" data-toggle="collapse">
<i class="glyphicon glyphicon-th"></i> 密码管理</a>
</div>
<ul id="userMenu" class="nav nav-list navbar-collapse.in menu-second">
<li><a href="/chgPass/"><i class="glyphicon glyphicon-send"></i> 登陆密码</a></li>
<li><a href="/chgKey/"><i class="glyphicon glyphicon-send"></i> 密钥密码</a></li>
</ul>
<div class="menu-first" ><a href="#fileMenu" data-toggle="collapse">
<i class="glyphicon glyphicon-th"></i> 文件传输</a>
</div>
<ul id="fileMenu" class="nav nav-list navbar-collapse.in menu-second">
<li><a href="/upFile/"><i class="glyphicon glyphicon-send"></i> 上传文件</a></li>
<li><a href="/downFile/"><i class="glyphicon glyphicon-send"></i> 下载文件</a></li>
</ul>
</div>
</div>
</div>
</div>
{% else %}
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="navbar-header"> <a class="navbar-brand" href="#">运维管理系统</a> </div>
<div class="navbar-header"> <a class="navbar-brand" href="#">Jumpserver</a> </div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="{{ index }}"><a href="/">主页</a></li>
@@ -107,6 +124,16 @@
<li><a href="/showPerm/"><i class="glyphicon glyphicon-send"></i> 查看权限</a></li>
<li><a href="/addPerm/"><i class="glyphicon glyphicon-send"></i> 添加权限</a></li>
</ul>
<div class="menu-first" ><a href="#logMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 日志审计</a></div>
<ul id="logMenu" class="nav nav-list navbar-collapse menu-second">
<li><a href="/logView/"><i class="glyphicon glyphicon-send"></i> 查看日志</a></li>
</ul>
<div class="menu-first" ><a href="#fileMenu" data-toggle="collapse">
<i class="glyphicon glyphicon-th"></i> 文件传输</a>
</div>
<ul id="fileMenu" class="nav nav-list navbar-collapse.in menu-second">
<li><a href="/upFile/"><i class="glyphicon glyphicon-send"></i> 上传文件</a></li>
<li><a href="/downFile/"><i class="glyphicon glyphicon-send"></i> 下载文件</a></li>
</ul>
</div>
</div>
@@ -119,6 +146,7 @@
{% block content %}{% endblock %}
</div>
</div>
</div>
</body>
</html>

View File

@@ -1,41 +1,41 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" role="form" method="post" action="" >
<fieldset >
<legend>添加PPTP用户</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="username" name="username" placeholder="用户名">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
</div>
</div>
<div class="form-group">
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">确认添加</button>
</div>
</div>
</fieldset>
</form>
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" role="form" method="post" action="/chgGroup/" >
<fieldset >
<legend>修改属组信息</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<div class="col-sm-4">
<input type="text" id="id" name="id" value="{{ group.id }}" hidden="hidden">
</div>
</div>
<div class="form-group">
<label for="oldname" class="col-sm-2 control-label">原来属组<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" id="oldname" name="oldname" class="form-control" value="{{ group.name }}" readOnly="readOnly">
</div>
</div>
<div class="form-group">
<label for="name" class="col-sm-2 control-label">属组<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" id="name" name="name" class="form-control" placeholder="属组">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">修改</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}

View File

@@ -1,39 +1,39 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" role="form" method="post" action="" >
<form class="form-horizontal" role="form" method="post" action="/chgGroup/" >
<fieldset >
<legend>修改OpenVPN登陆密码</legend>
<legend>修改IDC信息</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<label for="oldpass" class="col-sm-2 control-label">原来密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="用户名">
<input type="text" id="id" name="id" value="{{ idc.id }}" hidden="hidden">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">新密码<span style="color: red"> *</span></label>
<label for="oldname" class="col-sm-2 control-label">原来IDC<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
<input type="text" id="oldname" name="oldname" class="form-control" value="{{ idc.name }}" readOnly="readOnly">
</div>
</div>
<div class="form-group">
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<label for="name" class="col-sm-2 control-label">IDC<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
<input type="text" id="name" name="name" class="form-control" placeholder="IDC">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">确认修改</button>
<button class="btn btn-primary">修改</button>
</div>
</div>
</fieldset>

View File

@@ -14,11 +14,19 @@
</div>
{% endif %}
<div class="form-group">
<label for="oldpass" class="col-sm-2 control-label">原来的密码<span style="color: red"> *</span></label>
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="用户名">
<input type="text" class="form-control" id="username" name="username" placeholder="用户名" value="{{ username }}" readonly="readOnly">
</div>
</div>
{% if is_self %}
<div class="form-group">
<label for="oldpass" class="col-sm-2 control-label">原来的密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="原来密码">
</div>
</div>
{% endif %}
<div class="form-group">
<label for="password" class="col-sm-2 control-label">新密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
@@ -26,9 +34,9 @@
</div>
</div>
<div class="form-group">
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<label for="password_again" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
<input type="password" class="form-control" id="password_again" name="password_again" placeholder="确认密码">
</div>
</div>
<div class="form-group">

View File

@@ -14,11 +14,19 @@
</div>
{% endif %}
<div class="form-group">
<label for="oldpass" class="col-sm-2 control-label">原来密码<span style="color: red"> *</span></label>
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="用户名">
<input type="text" class="form-control" id="username" name="username" placeholder="用户名" value="{{ username }}" readonly="readOnly">
</div>
</div>
{% if is_self %}
<div class="form-group">
<label for="oldpass" class="col-sm-2 control-label">原来的密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="原来密码">
</div>
</div>
{% endif %}
<div class="form-group">
<label for="password" class="col-sm-2 control-label">新密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
@@ -26,14 +34,14 @@
</div>
</div>
<div class="form-group">
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<label for="password_again" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
<input type="password" class="form-control" id="password_again" name="password_again" placeholder="确认密码">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">修改</button>
<button class="btn btn-success">确认修改</button>
</div>
</div>
</fieldset>

View File

@@ -1,41 +0,0 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" role="form" method="post" action="" >
<fieldset >
<legend>修改PPTP VPN密码</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<label for="oldpass" class="col-sm-2 control-label">原来密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="用户名">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">新密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
</div>
</div>
<div class="form-group">
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">确认</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}

View File

@@ -0,0 +1,64 @@
{% extends 'base.html' %}
{% block content %}
<fieldset >
<legend>{{ username }}--修改sudo</legend>
<form class="form-horizontal" role="form" method="post" action="/chgSudo/" >
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<input type="text" name="username" value="{{ username }}" hidden="hidden">
<input type="text" class="form-control" name="add_host" placeholder="主机IP,多个逗号分隔">
<span class="input-group-btn">
<button class="btn btn-success" type="submit">新增主机</button>
</span>
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
</div><!-- /.row -->
</form>
<br>
<form class="form-horizontal" role="form" method="post" action="/chgSudo/" >
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<input type="text" name="username" value="{{ username }}" hidden="hidden">
<input type="text" class="form-control" name="del_host" placeholder="主机IP,多个逗号分隔">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">删除主机</button>
</span>
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
</div><!-- /.row -->
</form>
<br>
<form class="form-horizontal" role="form" method="post" action="/chgSudo/" >
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<input type="text" name="username" value="{{ username }}" hidden="hidden">
<input type="text" class="form-control" name="add_cmd" placeholder="添加命令,多个逗号分隔">
<span class="input-group-btn">
<button class="btn btn-info" type="submit">添加命令</button>
</span>
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
</div><!-- /.row -->
</form>
<br>
<form class="form-horizontal" role="form" method="post" action="/chgSudo/?delCMD=1" >
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<input type="text" name="username" value="{{ username }}" hidden="hidden">
<input type="text" class="form-control" name="del_cmd" placeholder="删除命令,多个逗号分隔">
<span class="input-group-btn">
<button class="btn btn-danger" type="submit">删除命令</button>
</span>
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
</div><!-- /.row -->
</form>
</fieldset>
{% endblock %}

View File

@@ -0,0 +1,76 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" role="form" method="post" action="/chgUser/" >
<fieldset >
<legend>修改用户信息</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if form.errors %}
<div class="alert alert-danger">
Please correct the error{{ form.errors|pluralize }} below.
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" id="username" name="username" class="form-control" value="{{ user.username }}" readOnly="readOnly">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<a href="/chgPass/?username={{ user.username }}">修改密码</a>
</div>
</div>
<div class="form-group">
<label for="key_pass" class="col-sm-2 control-label">密钥密码<span style="color: red"> *</span></label>
<div class="col-sm-4">
<a href="/chgKey/?username={{ user.username }}">修改密码</a>
</div>
</div>
<div class="form-group">
<label for="name" class="col-sm-2 control-label">姓名<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" id="name" name="name" class="form-control" value="{{ user.name }}" >
</div>
</div>
<div class="form-group">
<label for="group" class="col-sm-2 control-label">属组<span style="color: red"> *</span></label>
<div class="col-sm-4">
<select multiple name="group" id="group" class="form-control">
{% for group in groups %}
<option value="{{ group.name }}" >{{ group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label for="is_admin" class="col-sm-2 control-label">组admin</label>
<div class="col-sm-4">
<input type="radio" name="is_admin" id="is_admin" value="1">
</div>
</div>
<div class="form-group">
<label for="is_superuser" class="col-sm-2 control-label">超级admin</label>
<div class="col-sm-4">
<input type="radio" name="is_superuser" id="is_superuser" value="1">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">修改</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}

View File

@@ -0,0 +1,37 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" enctype="multipart/form-data" role="form" method="post" action="" >
<fieldset >
<legend>{{ username }} -- 下载文件</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<input type="text" name="username" value="{{ username }}" hidden="hidden">
<div class="form-group">
<label for="host" class="col-sm-2 control-label">服务器IP<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="host" name="host" placeholder="IP">
</div>
</div>
<div class="form-group">
<label for="path" class="col-sm-2 control-label">文件path<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="path" name="path" placeholder="文件绝对位置">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">下载</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}

View File

@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>错误页面</title>
<title>通知</title>
<style type="text/css">
body{

View File

@@ -4,8 +4,6 @@
<h1 style="color: green">说明:</h1>
<p>1. 登陆密码:可以修改登陆本系统的密码</p>
<p>2. 密钥密码:可以修改登陆服务器时密钥的密码</p>
<p>3. pptp密码可以修改登陆pptp类型vpn即 111.205.130.9的vpn的密码</p>
<p>4. Openvpn 可以修改登陆openvpn类型vpn即 111.205.130.4的vpn的密码</p>
<p><b>我的密钥:</b> <a href="/downKey/">下载</a></p>
<fieldset>
@@ -17,8 +15,8 @@
<th>ID</th>
<th>IP</th>
<th>Port</th>
<th>IDC</th>
<th>备注</th>
</tr>
</thead>
<tbody>
@@ -28,6 +26,7 @@
<td style="width: 5px">{{ asset.id }}</td>
<td style="width: 90px">{{ asset.ip }}</td>
<td style="width: 90px">{{ asset.port }}</td>
<td style="width: 90px">{{ asset.idc }}</td>
<td style="width: 90px">{{ asset.comment }}</td>
</tr>
{% endfor %}

View File

@@ -0,0 +1,54 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>信息</title>
<style type="text/css">
</style>
<script language="javascript">
var i=2;
window.setInterval("settime()",1000);
window.setTimeout("toload()",5000);
function settime(){
var divinner=document.getElementById("settime");
divinner.innerText=i;
i--;
}
function toload(){
history.go(-1);
}
</script>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5js"></script>
<![endif]-->
<link href="/static/css/bootstrap.css" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet">
<script src="/static/js/main.js"></script>
<script src="/static/js/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="/static/js/bootstrap.min.js"></script>
</head>
<body>
{% if msg %}
<div class="alert alert-success" style="margin-left: auto;margin-right: auto;margin-top: 60px;width:500px;"><b>成功:</b>{{ msg }}</div>
{% endif %}
{% if error %}
<div class="alert alert-danger" style="margin-left: auto;margin-right: auto;margin-top: 60px;width:500px;"><b>错误:</b>{{ error }}</div>
{% endif %}
</body>
</html>

View File

@@ -0,0 +1,125 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
<form method="post" action="">
<table class="table table-striped table-hover table-condensed">
<thead>
<tr>
<th>id</th>
<th>用户名</th>
<th>主机</th>
<th>监控</th>
<th>命令统计</th>
<th>阻断</th>
<th>开始时间</th>
<th>结束时间</th>
</tr>
</thead>
<tbody>
{% for log in logs.object_list %}
<tr>
<!--<td><input type="checkbox" name="selected" value="{{ log.id }}"></td>-->
<td>{{ log.id }}</td>
<td>{{ log.user }}</td>
<td>{{ log.host }}</td>
{% if log.finish %}
<td>监控</td>
<td><a href="/logHistory/?id={{ log.id }}" class="log_command">统计</a></td>
<td>阻断</td>
{% else %}
<td><a class='monitor' filename="{{ log.logfile }}">监控</a></td>
<td>命令统计</td>
<td><a href="/killSession/?id={{ log.id }}">阻断</a> </td>
{% endif %}
<td>{{ log.start_time|stamp2str }}</td>
<td>{{ log.end_time|stamp2str }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<script src="http://{{ web_socket_host }}/socket.io/socket.io.js"></script>
<script >
$.fn.webSocket = function(opt){
var st = {};
st = $.extend(st,opt);
var message = {};
var $this = $(this);
var genUid = function(){
return new Date().getTime()+""+Math.floor(Math.random()*899+100);
};
var init = function(e){
var socket = io.connect('ws://'+globalConfig.SOCKET_HOST);
var node = $(e.target);
message.id = genUid();
message.filename = node.attr('filename');
BootstrapDialog.show({message:function(){
var escapeString = function (html){
var elem = document.createElement('div')
var txt = document.createTextNode(html)
elem.appendChild(txt)
return elem.innerHTML;
}
var tag = $('<div id="log" style="height:300px;overflow: auto;"></div>');
//告诉服务器端有用户登录
socket.emit('login', {userid:message.id, filename:message.filename});
socket.on('message',function(obj){
//去除log中的颜色控制字符
var regx = /\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]/g;
tag.append('<p>'+escapeString(obj.content.replace(regx,''))+'</p>');
tag.animate({ scrollTop: tag[0].scrollHeight}, 1);
});
return tag[0];
} ,
title:'实时监控:',
onhide:function(){
socket.emit('disconnect');
}});
}
$this.on("click",function(e){
init(e);
return false;
});
}
$('.log_command').on('click',function(){
var url = $(this).attr('href');
$.ajax({url:url,success:function(data){
BootstrapDialog.show({title:'命令统计',message:data});
}});
return false;
})
globalConfig = {
SOCKET_HOST: "{{ web_socket_host }}"
}
$(".monitor").webSocket()
</script>
<!--<button class="btn btn-primary">删除</button>-->
</form>
<nav>
<ul class="pager">
{% if logs.has_previous %}
<li><a href="?page={{ logs.previous_page_number }}">上一页</a></li>
{% endif %}
<span class="current">
Page {{ logs.number }} of {{ logs.paginator.num_pages }}.
</span>
{% if logs.has_next %}
<li><a href="?page={{ logs.next_page_number }}">下一页</a></li>
{% endif %}
</ul>
</nav>
{% endblock %}

View File

@@ -1,43 +0,0 @@
{% extends 'base.html' %}
{% block content %}
<form method="post" action="">
<div style="float: left; width: 400px;">
<div class="row">
<div class="col-lg-12">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">IP(s)</button>
</span>
<input type="text" class="form-control" name="ip" placeholder="IP or IPS" value={{ old_ip }}>
</div><!-- /input-group -->
<span class="help-block" style="margin-left: 20px;"> 输入一个IP,或者多个IP逗号隔开。</span>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">CMD</button>
</span>
<input type="text" class="form-control" name="cmd" placeholder="Command or Commands">
</div><!-- /input-group -->
<span class="help-block" style="margin-left: 20px;"> 输入在执行的命令,多个命令分号隔开.</span>
</div>
</div>
</div>
<div style="float: left; margin-top: 74px; margin-left: 40px;">
<button type="submit" class="btn btn-primary">执行</button>
</div>
<div style="clear: both;"></div>
</form>
{% if stdout %}
<div class="alert alert-success">{{ stdout }}</div>
{% endif %}
{% if stderr %}
<div class="alert alert-warning">{{ stderr }}</div>
{% endif %}
{% endblock %}

View File

@@ -13,6 +13,7 @@
<th>ID</th>
<th>IP</th>
<th>Port</th>
<th>IDC</th>
<th>备注</th>
</tr>
@@ -24,6 +25,7 @@
<td style="width: 5px">{{ asset.id }}</td>
<td style="width: 90px">{{ asset.ip }}</td>
<td style="width: 90px">{{ asset.port }}</td>
<td style="width: 90px">{{ asset.idc }}</td>
<td style="width: 90px">{{ asset.comment }}</td>
</tr>
{% endfor %}
@@ -31,4 +33,19 @@
</table>
<button class="btn btn-primary">删除</button></td>
</form>
<nav>
<ul class="pager">
{% if assets.has_previous %}
<li><a href="?page={{ assets.previous_page_number }}">上一页</a></li>
{% endif %}
<span class="current">
Page {{ assets.number }} of {{ assets.paginator.num_pages }}.
</span>
{% if assets.has_next %}
<li><a href="?page={{ assets.next_page_number }}">下一页</a></li>
{% endif %}
</ul>
</nav>
{% endblock %}

View File

@@ -10,20 +10,18 @@
<thead>
<tr>
<th><input onclick="selectAll()" type="checkbox" name="select_all" style="select_all" id="select_all"/></th>
<th>ip</th>
<th>用户名</th>
<th>端口</th>
<th>sudo</th>
<th>ID</th>
<th>属组</th>
<th>修改</th>
</tr>
</thead>
<tbody>
{% for server in servers %}
{% for group in groups %}
<tr>
<td><input type="checkbox" name="selected" value="{{ server.id }}"></td>
<td>{{ server.ip }}</td>
<td>{{ server.username }}</td>
<td>{{ server.port }}</td>
<td>{{ server.sudo }}</td>
<td><input type="checkbox" name="selected" value="{{ group.id }}"></td>
<td>{{ group.id }}</td>
<td>{{ group.name }}</td>
<td><a href="/chgGroup/?id={{ group.id }}">修改</a></td>
</tr>
{% endfor %}
</tbody>

View File

@@ -0,0 +1,31 @@
{% extends 'base.html' %}
{% block content %}
<form method="post" action="">
{% if info %}
<p class="alert alert-success">
{{ info }}
</p>
{% endif %}
<table class="table table-striped table-hover table-condensed">
<thead>
<tr>
<th><input onclick="selectAll()" type="checkbox" name="select_all" style="select_all" id="select_all"/></th>
<th>ID</th>
<th>IDC</th>
<th>修改</th>
</tr>
</thead>
<tbody>
{% for idc in idcs %}
<tr>
<td><input type="checkbox" name="selected" value="{{ idc.id }}"></td>
<td>{{ idc.id }}</td>
<td>{{ idc.name }}</td>
<td><a href="/chgIDC/?id={{ idc.id }}">修改</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<button class="btn btn-primary">删除</button>
</form>
{% endblock %}

View File

@@ -0,0 +1,19 @@
{% extends 'base.html' %}
{% block content %}
<fieldset >
<legend>{{ username }}</legend>
<b>允许sudo的主机</b>
<ul class="list-group">
{% for host in sudoHost %}
<li class="list-group-item">{{ host }}</li>
{% endfor %}
</ul>
<br />
<b>允许的sudo命令</b>
<ul class="list-group">
{% for cmd in sudoCommand %}
<li class="list-group-item">{{ cmd }}</li>
{% endfor %}
</ul>
</fieldset>
{% endblock %}

View File

@@ -13,8 +13,14 @@
<th>ID</th>
<th>用户名</th>
<th>姓名</th>
<th>属组</th>
<th>is_admin</th>
<th>is_superuser</th>
<th>Email</th>
<th>Key</th>
<th>密钥</th>
<th>用户信息</th>
<th>sudo</th>
<th>sudo</th>
</tr>
</thead>
<tbody>
@@ -24,8 +30,18 @@
<td>{{ user.id }}</td>
<td>{{ user.username }}</td>
<td>{{ user.name }}</td>
<td>
{% for group in user.group.all %}
{{ group.name }}
{% endfor %}
</td>
<td>{{ user.is_admin }}</td>
<td>{{ user.is_superuser }}</td>
<td>{{ user.email }}</td>
<td><a href="/downKey/">下载</a></td>
<td><a href="/downKey/?username={{ user.username }}">下载</a></td>
<td><a href="/chgUser/?username={{ user.username }}">修改</a></td>
<td><a href="/showSudo/?username={{ user.username }}">查看</a></td>
<td><a href="/chgSudo/?username={{ user.username }}">修改</a></td>
</tr>
{% endfor %}
</tbody>

View File

@@ -1,90 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>运维管理系统</title>
<link rel="shortcut icon" type="image/x-icon" href="http://img.youlu.com/web/favicon.gif" />
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5js"></script>
<![endif]-->
<link href="/static/css/bootstrap.css" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet">
<script src="/static/js/main.js"></script>
<script src="/static/js/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="/static/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="navbar-header"> <a class="navbar-brand" href="#">运维管理系统</a> </div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/">主页</a></li>
<li><a href="#">用户管理</a></li>
<li><a href="#">命令执行</a></li>
<li><a href="#">主机管理</a></li>
</ul>
<div class="btn-group navbar-right">
<button type="button" class="btn btn-primary dropdown-toggle " data-toggle="dropdown">
{{ name }}<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-logout">
<li class="dropdown-logout"><a href="/logout/">退出</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row row-offcanvas row-offcanvas-right">
<div class="col-xs-12 col-sm-3 sidebar-offcanvas" id="sidebar" role="navigation">
<div class="row">
<div class="col-md-12">
<div class="row>
<!--Sidebar content-->
<div class="sidebar-menu">
<div class="menu-first" ><a href="#userMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 用户管理</a></div>
<ul id="userMenu" class="nav nav-list navbar-collapse.in menu-second">
<li><a href="/showUser/"><i class="glyphicon glyphicon-send"></i> 查看用户</a></li>
<li><a href="/addUser/"><i class="glyphicon glyphicon-send"></i> 添加用户</a></li>
</ul>
<div class="menu-first" ><a href="#monitorMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 执行命令</a></div>
<ul id="monitorMenu" class="nav nav-list navbar-collapse.in menu-second">
<li><a href="/runCommand/"><i class="glyphicon glyphicon-send"></i> 执行命令</a></li>
<li><a href="/addServer/"><i class="glyphicon glyphicon-send"></i> 添加主机</a></li>
<li><a href="#"><i class="glyphicon glyphicon-send"></i> 环境</a></li>
</ul>
<div class="menu-first" ><a href="#articleMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 主机管理</a></div>
<ul id="articleMenu" class="nav nav-list navbar-collapse menu-second">
<li><a href="/showAssets/"><i class="glyphicon glyphicon-send"></i> 主机列表</a></li>
<li><a href="/addAssets/"><i class="glyphicon glyphicon-send"></i> 添加主机</a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Go!</button>
</span>
<input type="text" class="form-control">
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
<div class="col-lg-6">
<div class="input-group">
<input type="text" class="form-control">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Go!</button>
</span>
</div><!-- /input-group -->
</div><!-- /.col-lg-6 -->
</div><!-- /.row -->
</div>
</body>
</html>

View File

@@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% block content %}
<form class="form-horizontal" enctype="multipart/form-data" role="form" method="post" action="" >
<fieldset >
<legend>{{ username }} -- 上传文件</legend>
{% if error %}
<div class="alert alert-danger">
{{ error }}
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endif %}
<input type="text" name="username" value="{{ username }}" hidden="hidden">
<div class="form-group">
<label for="host" class="col-sm-2 control-label">服务器IP<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="host" name="host" placeholder="IP">
</div>
</div>
<div class="form-group">
<label for="path" class="col-sm-2 control-label">上传目录<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="text" class="form-control" id="path" name="path" placeholder="服务器目录">
</div>
</div>
<div class="form-group">
<label for="file" class="col-sm-2 control-label">选择文件<span style="color: red"> *</span></label>
<div class="col-sm-4">
<input type="file" class="form-control" id="file" name="file" placeholder="点击添加">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button class="btn btn-primary">上传</button>
</div>
</div>
</fieldset>
</form>
{% endblock %}

View File

@@ -0,0 +1,92 @@
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var spawn = require('child_process').spawn;
var Tail = require('tail').Tail;
app.get('/', function(req, res){
res.send('<h1>Welcome Realtime Server</h1>');
});
//在线用户
var onlineUsers = {};
//当前在线人数
var onlineCount = 0;
io.on('connection', function(socket){
//console.log('a user connected');
//监听新用户加入
socket.on('login', function(obj){
//将新加入用户的唯一标识当作socket的名称后面退出的时候会用到
socket.name = obj.userid;
socket.fileName = obj.filename;
var tail = new Tail(obj.filename);
//console.log(obj.filename);
tail.on('line',function(data) {
//console.log(data);
var newData = {userid:obj.userid,username:obj.username,content:data};
socket.emit('message',newData);
});
// var tail = spawn("tail", ['-f', obj.filename]);
// tail.stdout.on('data',function(data){
// var content = data.toString();
// //console.log(content);
// var newData = {userid:obj.userid,username:obj.username,content:content};
// socket.emit('message',newData);
// });
socket.tail = tail;
//检查在线列表,如果不在里面就加入
if(!onlineUsers.hasOwnProperty(obj.userid)) {
onlineUsers[obj.userid] = obj.username;
//在线人数+1
onlineCount++;
}
//向所有客户端广播用户加入
//io.emit('login', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj});
//console.log(obj.username+'加入了聊天室');
});
//监听用户退出
socket.on('disconnect', function(){
//将退出的用户从在线列表中删除
if(onlineUsers.hasOwnProperty(socket.name)) {
//退出用户的信息
var obj = {userid:socket.name, username:onlineUsers[socket.name]};
if( socket.tail){
socket.tail.unwatch();
}
//删除
delete onlineUsers[socket.name];
//在线人数-1
onlineCount--;
//向所有客户端广播用户退出
//io.emit('logout', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj});
////console.log(obj.username+'退出了聊天室');
}
});
//监听用户发布聊天内容
socket.on('message', function(obj){
//向所有客户端广播发布的消息
//io.emit('message', obj);
socket.emit('message',obj);
////console.log(obj.username+'说:'+obj.content);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});

View File

@@ -0,0 +1,11 @@
{
"name": "web-socket",
"version": "0.0.1",
"description": "my first realtime server",
"dependencies": {
"express": "~4.10.1",
"socket.io": "~1.2.0",
"node-tail": "0.0.4",
"tail": "~0.4.0"
}
}

1
webroot/__init__.py Normal file
View File

@@ -0,0 +1 @@
__author__ = 'Hudie'