自动化运维之 Kerberos 账号信息管理平台

简介:

公司的自动化项目之一

公司的服务器超多,需要一个用来管理服务器权限的系统。

主要是实现 用一个账号,可以让你登录所有的服务器,也可以让你身无无分文。

就是这样的一个操作的平台。



1
2
3
4
5
6
7
8
9
10
5 - 25
数据库的展现已经做完~    下一步把最多ip和账号给显示出来
加载了 chosen 引起了 右下角的点击关闭 把他的js去掉就行了
改变了用户的登录的方式,把session改成cookies
查到的数据,打印到表格里面,并且前面放一个checkbox   可以实现多选,进行删除。
要做的~
量多的话,可以上传一个文本,文本里面都是要清除的账号。
这样的话,就不用一个个的点了。
还有一个就是数据库的备份,然后针对服务器进行数据的分发恢复。
发现一个问题,就是批量查询mailid的时候,特别的慢,打算把数据放到redis里面。


1
2
3
4
5 - 27
1   触发后端更新之后,在前端会实时发起ajax的请求,得到的数据主要是 已经完成,没完成的。 另外就是一个进度条的展现。
2   登录的页面不从数据库里面取值,而是从公司的ldap里面取状态。用来统一的验证。
3   各个日志的下载的连接,判断文件大小,要是小的话,专门 return 到info.html页面里去


1
2
3
4
5
6
7
8
6 - 1 6 - 7
为了增加性能,加了uwsgi的多线程。 测试结果,会在一个函数内堵塞,不影响其他人的访问别的函数。
用户的判断已经改用数据库取值
改了后端,针对删除的判断,要是有的话,就直接跳出来,不用进行后期的日志的写入
远程控制的界面和功能已经写完了~
后端基本ok,加了一个进度条。 现在想做一个专门处理后端的队列系统。
现在日志的解析还没有压力,等有压力的时候,从后端开始分。
现在的后端更新可以用python auto_manage_kerberos.py -db dbupdate 回头研究下,打印出日志来







193120283.jpg


1.Client将之前获得TGT和要请求的服务信息(服务名等)发送给KDC,KDC中的Ticket Granting Service将为Client和Service之间生成一个Session Key用于Service对Client的身份鉴别。然后KDC将这个Session Key和用户名,用户地址(IP),服务名,有效期, 时间戳一起包装成一个Ticket(这些信息最终用于Service对Client的身份鉴别)发送给Service,不过Kerberos协议并没有直接将Ticket发送给Service,而是通过Client转发给Service.所以有了第二步。

2.此时KDC将刚才的Ticket转发给Client。由于这个Ticket是要给Service的,不能让Client看到,所以KDC用协议开始前KDC与Service之间的密钥将Ticket加密后再发送给Client。同时为了让Client和Service之间共享那个秘密(KDC在第一步为它们创建的Session Key), KDC用Client与它之间的密钥将Session Key加密随加密的Ticket一起返回给Client。

3.为了完成Ticket的传递,Client将刚才收到的Ticket转发到Service. 由于Client不知道KDC与Service之间的密钥,所以它无法算改Ticket中的信息。同时Client将收到的Session Key解密出来,然后将自己的用户名,用户地址(IP)打包成Authenticator用Session Key加密也发送给Service。

4.Service 收到Ticket后利用它与KDC之间的密钥将Ticket中的信息解密出来,从而获得Session Key和用户名,用户地址(IP),服务名,有效期。然后再用Session Key将Authenticator解密从而获得用户名,用户地址(IP)将其与之前Ticket中解密出来的用户名,用户地址(IP)做比较从而验证Client的身份。

5.如果Service有返回结果,将其返回给Client。



kerberos配置的大体流程

大家可以参考下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
先配KDC服务器,然后再配Ktelnetd,Krlogind,Krsh服务器,最后就可以使用krb5-workstation提供的telnet,rlogin,rsh来登录这些服务了。下面是安装步骤:
  
   1 、生成kerberos的本地数据库
  kdb5_util create -r EXAMPLE.COM -s
  这个命令用来生成kerberos的本地数据库,包括几个文件:principal,principal.OK,principal.kadm5,principal.kadm5.lock. -r 指定realm(kerberos术语),我们随便取一个叫EXAMPLE.COM.
  
   2 、生成账号
   kerberos用principal(kerberos术语)来表示realm下的一个帐户,表示为primary/instance@realm,举个例子就是username/ 9.181 . 92.90 @EXAMPLE.COM,这里假设 9.181 . 92.90 是你机器的ip地址.
  
  在数据库中加入管理员帐户:
  /usr/kerberos/sbin/kadmin.local
  kadmin.local: addprinc admin/admin@EXAMPLE.COM
  在数据库中加入用户的帐号:
  kadmin.local: addprinc username/ 9.181 . 92.90 @EXAMPLE.COM
  在数据库中加入Ktelnetd,Krlogind,Krshd公用的帐号:
  kadmin.local: addprinc -randkey host/ 9.181 . 92.90 @EXAMPLE.COM
  
   3 、检查/ var /kerberos/krb5kdc/kadm5.keytab是否有下列语句:
  */admin@EXAMPLE.COM *
  若没有,那么就添上。
  
   4 、修改/etc/krb5.conf文件,修改所有的realm为EXAMPLE.COM,并且加入下列句子
  kdc =  9.181 . 92.90 : 88
  admin_server =  9.181 . 92.90 : 749
  
   5 、在/etc/krb.conf中加入下列语句:
  EXAMPLE.COM
  EXAMPLE.COM  9.181 . 92.90 : 88
  EXAMPLE.COM  9.181 . 92.90 : 749  admin server
  
   6 、启动kdc服务器和Ktelnetd,Krlogind,Krshd
  /etc/init.d/krb5kdc restart
  chkconfig klogin on
  chkconfig kshell on
  chkconfig eklogin on
  chkconfig krb5-telnet on
  /etc/init.d/xinetd restart
  
   7 、制作本地缓存
  将username/ 9.181 . 92.90 @EXAMPLE.COM的credentials(kerberos术语)取到本地做为cache,这样以后就可以不用重复输入password了。
  kinit username/ 9.181 . 92.90
  如果顺利的话,在/tmp下面会生成文件krb5*;这步如果不通,那么就必须检查以上步骤是否有漏。
  可以用klist命令来查看credential。
  
   8 、导出用户密匙
  export host/ 9.181 . 92.90 @EXAMPLE.COM的key到/etc/krb5.keytab,Ktelnetd、Krlogind和Krshd需要/etc/krb5.keytab来验证username/ 9.181 . 92.90 的身份。
  kadmin.local: ktadd -k /etc/krb5.keytab host/ 9.181 . 92.90
  
   9 、修改~/.k5login文件
  在其中加入username/ 9.181 . 92.90 @EXAMPLE.COM,表示允许username/ 9.181 . 92.90 @EXAMPLE.COM登录该帐户
  
  cat username/ 9.181 . 92.90 @EXAMPLE.COM >>~/.k5login
  
   10 、测试kerberos客户端
  krsh  9.181 . 92.90  -k EXAMPLE.COM ls
  krlogin  9.181 . 92.90  -k EXAMPLE.COM
  rlogin  9.181 . 92.90  -k EXAMPLE.COM
  rsh  9.181 . 92.90  -k EXAMPLE.COM
  telnet -x  9.181 . 92.90  -k EXAMPLE.COM



ajax 显示进度条的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<!DOCTYPE HTML PUBLIC  "-//W3C//DTD HTML 4.01 Transitional//EN" >
<html>
   <head>
     <title>Ajax Progress Bar</title>
     <script type= "text/javascript" >...
         var  xmlHttp;
         var  key;
         function  createXMLHttpRequest() ...{
             if  (window.ActiveXObject) ...{
                 xmlHttp =  new  ActiveXObject( "Microsoft.XMLHTTP" );
             }
             else  if  (window.XMLHttpRequest) ...{
                 xmlHttp =  new  XMLHttpRequest();
             }
         }
         function  go() ...{
             createXMLHttpRequest();
             clearBar();
             var  url =  "ProgressBarServlet?task=create" ;
             var  button = document.getElementById( "go" );
             button.disabled =  true ;
             xmlHttp.open( "GET" , url,  true );
             xmlHttp.onreadystatechange = goCallback;
             xmlHttp.send( null );
         }
         function  goCallback() ...{
             if  (xmlHttp.readyState ==  4 ) ...{
                 if  (xmlHttp.status ==  200 ) ...{
                     setTimeout( "pollServer()" 2000 );
                 }
             }
         }
                                                                                                                                                                                                                                                                         
         function  pollServer() ...{
             createXMLHttpRequest();
             var  url =  "ProgressBarServlet?task=poll&key="  + key;
             xmlHttp.open( "GET" , url,  true );
             xmlHttp.onreadystatechange = pollCallback;
             xmlHttp.send( null );
         }
                                                                                                                                                                                                                                                                         
         function  pollCallback() ...{
             if  (xmlHttp.readyState ==  4 ) ...{
                 if  (xmlHttp.status ==  200 ) ...{
                     var  percent_complete = xmlHttp.responseXML.getElementsByTagName( "percent" )[ 0 ].firstChild.data;
                     var  progress = document.getElementById( "progress" );
                     var  progressPersent = document.getElementById( "progressPersent" );
      progress.width = percent_complete +  "%" ;
      progressPersent.innerHTML = percent_complete +  "%" ;
                     if  (percent_complete <  100 ) ...{
                         setTimeout( "pollServer()" 2000 );
                     else  ...{
                         document.getElementById( "complete" ).innerHTML =  "Complete!" ;
                         //document.getElementById("go").disabled = false;
                     }
                 }
             }
         }
  function  clearBar() ...{
    var  progress_bar = document.getElementById( "progressBar" );
    var  progressPersent = document.getElementById( "progressPersent" );
    var  complete = document.getElementById( "complete" );
    progress_bar.style.visibility =  "visible"
    progressPersent.innerHTML =  "&nbsp;" ;
    complete.innerHTML =  "Begin to upload this file..." ;
  }
     </script>
   </head>
<body>
<div id= "progressBar"  style= "padding:0px;border:solid black 0px;visibility:hidden" >
<table width= "300"  border= "0"  cellspacing= "0"  cellpadding= "0"   align= "center" >
   <tr>
     <td align= "center"  id= "progressPersent" > 86 %</td>
   </tr>
   <tr >
     <td>
  <table width= "100%"  border= "1"  cellspacing= "0"  cellpadding= "0"  bordercolor= "#000000" >
   <tr>
     <td>
  <table width= "1%"  border= "0"  cellspacing= "0"  cellpadding= "0"  bgcolor= "#FF0000"  id= "progress" >
               <tr>
                 <td>&nbsp;</td>
               </tr>
             </table></td>
   </tr>
</table>
</td>
   </tr>
   <tr>
     <td align= "center"  id= "complete" >completed</td>
   </tr>
</table>
</div>
<input id =  "go"  name= "run"  type= "button"  value= "run"  onClick= "go();" >
</body>
</html>



cookie的配置


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python
#coding=utf-8
                                                                                                                                                                                                                                  
from  flask  import  Flask,url_for,request,render_template,redirect,abort,escape,session
from  werkzeug  import  secure_filename
                                                                                                                                                                                                                                  
print  __name__
app  =  Flask(__name__)
app.secret_key  =  'hello'
                                                                                                                                                                                                                                  
@app .route( '/' )
def  index():
     return  "hello flask"
                                                                                                                                                                                                                                  
@app .route( '/user/<username>' )
def  show_username(username):
     return  username
                                                                                                                                                                                                                                  
@app .route( '/post/<int:post_id>' )
def  show_post(post_id):
     return  'post_id:%d'  %  post_id
                                                                                                                                                                                                                                  
#if you visit /projects will redirect /projects/
@app .route( '/projects/' )
def  projects():
     return  'the project page'
                                                                                                                                                                                                                                  
#if you visit /about/ will return 404 error
@app .route( '/about' )
def  about():
     return  'the about page'
                                                                                                                                                                                                                                  
@app .route( '/upload/' ,methods = [ 'GET' , 'POST' ])
def  upload_file():
     if  request.method  = =  'POST' :
         =  request.files[ 'the_file' ]
         f.save( './' + secure_filename(f.filename))
         return  secure_filename(f.filename)
     else :
         return  render_template( 'upload_file.html' )
                                                                                                                                                                                                                                  
@app .route( '/redirect/' )
def  test_redirect():
     return  redirect(url_for( 'test_error' ))
                                                                                                                                                                                                                                  
@app .route( '/test_error/' )
def  test_error():
     #中断请求,并返回错误码
     abort( 404 )
                                                                                                                                                                                                                                  
@app .errorhandler( 404 )
def  page_not_found(error):
     print  error
     return  render_template( 'page_not_found.html' ), 404
                                                                                                                                                                                                                                  
@app .route( '/index/' )
def  test_session():
     if  'username'  in  session:
         return  'logged in as %s'  %  escape(session[ 'username' ])
     return  redirect(url_for( 'login' ))
                                                                                                                                                                                                                                  
@app .route( '/login/' ,methods = [ 'GET' , 'POST' ])
def  login():
     if  request.method  = =  'POST' :
         session[ 'username' =  request.form[ 'username' ]
         return  redirect(url_for( 'test_session' ))
     else :
         return  '''
         <form action="/login/" method="post">
         <input type=text name=username>
         <input type=submit value=login>
         </form>
         '''
@app .route( '/logout/' )
def  logout():
     session.pop( 'username' , None )
     return  redirect(url_for( 'test_session' ))
                                                                                                                                                                                                                                  
with app.test_request_context():
     print  url_for( 'index' )
     print  url_for( 'index' , next = '/' )
     print  url_for( 'show_username' ,username = 'alex' )
                                                                                                                                                                                                                                  
@app .route( '/setcookie' )
def  set_cookie():
     if  'num'  in  request.cookies:
         count  =  int (request.cookies[ 'num' ])  +  1
     else :
         count  =  0
                                                                                                                                                                                                                                  
     #每个view最后返回的都是response对象,render_template内部做了处理
     #也可以这样表示response = make_response(render_template('index.html', count=100))
     #不设置max_age和expires时,默认是会话cookie,浏览器关闭后cookie就失效
     #domain可以设置跨域cookie,如domain=".example.com",这样cookie可以 被"www.example.com,alex.example.com"共享
     response  =  app.make_response( str (count))
     response.set_cookie( 'num' ,value = count,max_age = None ,expires = None ,domain = None )
     return  response
                                                                                                                                                                                                                                  
if  __name__  = =  '__main__' :
     app.run(host = "localhost" ,port = 8888 ,debug = True )



python管理kerberos的库的用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import  kerberos
import  httplib
# setup kerb
_ignore, ctx  =  authGSSClientInit(‘HTTP@myhost.example.com’, gssflags = GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG|GSS_C_SEQUENCE_FLAG)
_ignore  =  authGSSClientStep(ctx, ”)
tgt  =  authGSSClientResponse(ctx)
# setup http connection
servername, port  =  (‘myhost.exmple.com’,  443 )
=  httplib.HTTPSConnection(servername, port)
h.connect()
# Setup Headers
http_conn.putrequest(“GET”, “ / XMLRPC / ”)
if  tgt:
h.putheader(‘Authorization’, ‘Negotiate  % s’  %  tgt)
h.endheaders()
# Make http call
resp  =  http_conn.getresponse()
if  resp.status ! =  200 :
print  “Error:  % s”  %  str (resp.status)
return  None
#Check for kerb header
krb_reply  =  resp.getheader(‘WWW - Authenticate’)
if  not  krb_reply:
print  “Server did  not  send kerberos reply”
return  None
# print html contents
print  resp.read()


python ldap的操作的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def ldap_getcn(username):
     try :
         l = ldap.open(LDAP_HOST)
         l.protocol_version = ldap.VERSION3
         l.simple_bind(LDAP_BIND, LDAP_PASS)
         searchScope = ldap.SCOPE_SUBTREE
         searchFilter =  "uid=*"  + username +  "*"
         resultID = l.search(LDAP_BASE, searchScope, searchFilter, None)
         result_set = []
         while  1 :
             result_type, result_data = l.result(resultID,  0 )
             if  (result_data == []):
                 break
             else :
                 if  result_type == ldap.RES_SEARCH_ENTRY:
                     result_set.append(result_data)
         return  result_set[ 0 ][ 0 ][ 1 ][ 'cn' ][ 0 ]
     except ldap.LDAPError, e:
         print e


202043443.jpg

202044132.jpg


000639188.jpg


135817168.jpg

075444858.jpg



001624588.jpg


001008356.jpg


001401976.jpg


171850133.jpg

172003997.jpg

103415204.jpg

075247386.jpg

212055144.png

202226843.jpg



 本文转自 rfyiamcool 51CTO博客,原文链接:http://blog.51cto.com/rfyiamcool/1210166,如需转载请自行联系原作者





相关文章
|
8月前
|
数据采集 运维 监控
爬虫与自动化技术深度解析:从数据采集到智能运维的完整实战指南
本文系统解析爬虫与自动化核心技术,涵盖HTTP请求、数据解析、分布式架构及反爬策略,结合Scrapy、Selenium等框架实战,助力构建高效、稳定、合规的数据采集系统。
1217 62
爬虫与自动化技术深度解析:从数据采集到智能运维的完整实战指南
|
8月前
|
API 调度 虚拟化
VMware Cloud Foundation Automation 9.0.1.0 发布 - 私有云自动化平台
VMware Cloud Foundation Automation 9.0.1.0 发布 - 私有云自动化平台
373 3
VMware Cloud Foundation Automation 9.0.1.0 发布 - 私有云自动化平台
|
安全 Linux 虚拟化
Palo Alto Cortex XSOAR 8.8 for ESXi - 安全编排、自动化和响应 (SOAR) 平台
Palo Alto Cortex XSOAR 8.8 for ESXi - 安全编排、自动化和响应 (SOAR) 平台
386 0
Palo Alto Cortex XSOAR 8.8 for ESXi - 安全编排、自动化和响应 (SOAR) 平台
|
9月前
|
运维 监控 自动驾驶
低代码运维平台:是“运维福音”,还是“甩手掌柜”?
低代码运维平台:是“运维福音”,还是“甩手掌柜”?
243 29
|
9月前
|
运维 Linux 网络安全
自动化真能省钱?聊聊运维自动化如何帮企业优化IT成本
自动化真能省钱?聊聊运维自动化如何帮企业优化IT成本
267 4
|
12月前
|
人工智能 搜索推荐 测试技术
通义灵码 Agent+MCP:打造自动化菜品推荐平台,从需求到部署实现全流程创新
通过通义灵码编程智能体模式和 MCP 的集成,开发者可以高效构建在线菜品推荐网站。智能体模式大幅提升了开发效率,MCP 服务则为功能扩展提供了无限可能。
|
JavaScript 搜索推荐 前端开发
通义灵码2.5智能体模式联合MCP:打造自动化菜品推荐平台,实现从需求到部署的全流程创新
本项目利用通义灵码2.5的智能体模式与MCP服务,构建在线点餐推荐网站。基于Qwen3模型,实现从需求到代码生成的全流程自动化,集成“今天吃什么”和EdgeOne MCP服务,提供个性化推荐、偏好管理等功能。技术架构采用React/Vue.js前端与Node.js后端,结合MCP工具链简化开发。项目涵盖功能测试、部署及未来扩展方向,如餐厅推荐、语音交互等,展示高效开发与灵活扩展能力。
|
11月前
|
运维 监控 安全
从实践到自动化:现代运维管理的转型与挑战
本文探讨了现代运维管理从传统人工模式向自动化转型的必要性与路径,分析了传统运维的痛点,如效率低、响应慢、依赖经验等问题,并介绍了自动化运维在提升效率、降低成本、增强系统稳定性与安全性方面的优势。结合技术工具与实践案例,文章展示了企业如何通过自动化实现运维升级,推动数字化转型,提升业务竞争力。
|
存储 人工智能 Kubernetes
VMware Cloud Foundation Automation 9.0 发布 - 私有云自动化平台
VMware Cloud Foundation Automation 9.0 发布 - 私有云自动化平台
198 0