使用salt-api来搭建salt自动化平台
发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,一、介绍通常使用saltstack都是在master的服务器上直接命令操作,这个对于运维人员来说不是什么大事,但是也会有出错的时候,而一旦出错,就会有不可挽回的后果。二、框架这里使用django框架,
千家信息网最后更新 2025年01月31日使用salt-api来搭建salt自动化平台
一、介绍
通常使用saltstack都是在master的服务器上直接命令操作,这个对于运维人员来说不是什么大事,但是也会有出错的时候,而一旦出错,就会有不可挽回的后果。
二、框架
这里使用django框架,通过对salt-api的封装,传入命令,执行api,将结果返回到页面上显示。注意:为了防止误操作,我们对传入的命令进行了检查,所有被定义的危险命令将不会被执行。(我这里为了简单,所以定义了可以被执行的命令。),前端使用了jquery+ajax的方式来不刷新页面就将结果显示在页面上的方式。
三、salt-api的安装
网上教程很多,我这里就不再废话了。
四、django代码
1)、整体结构
2)、salt_api.py(这里参照了github上dzhops的代码)
# -*- coding: utf-8 -*-import urllib2, urllib, jsonimport requestsimport jsonimport sslssl._create_default_https_context = ssl._create_unverified_contextclass SaltAPI(object): def __init__(self, url, username, password): self.__url = url.rstrip('/') self.__user = username self.__password = password self.__token_id = self.saltLogin() def saltLogin(self): params = {'eauth': 'pam', 'username': self.__user, 'password': self.__password} encode = urllib.urlencode(params) obj = urllib.unquote(encode) headers = {'X-Auth-Token': ''} url = self.__url + '/login' req = urllib2.Request(url, obj, headers) opener = urllib2.urlopen(req) content = json.loads(opener.read()) try: token = content['return'][0]['token'] return token except KeyError: raise KeyError def postRequest(self, obj, prefix='/'): url = self.__url + prefix headers = {'X-Auth-Token': self.__token_id} req = urllib2.Request(url, obj, headers) opener = urllib2.urlopen(req) content = json.loads(opener.read()) return content def masterToMinionContent(self, tgt, fun, arg): ''' Master控制Minion,返回的结果是内容,不是jid; 目标参数tgt是一个如下格式的字符串:'*' 或 'zhaogb-201' ''' if tgt == '*': params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg} else: params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg, 'expr_form': 'list'} obj = urllib.urlencode(params) content = self.postRequest(obj) result = content['return'][0] return result def allMinionKeys(self): ''' 返回所有Minion keys; 分别为 已接受、待接受、已拒绝; :return: [u'local', u'minions_rejected', u'minions_denied', u'minions_pre', u'minions'] ''' params = {'client': 'wheel', 'fun': 'key.list_all'} obj = urllib.urlencode(params) content = self.postRequest(obj) minions = content['return'][0]['data']['return']['minions'] minions_pre = content['return'][0]['data']['return']['minions_pre'] minions_rej = content['return'][0]['data']['return']['minions_rejected'] # return minions, minions_pre, minions_rej return minions def actionKyes(self, keystrings, action): ''' 对Minion keys 进行指定处理; :param keystrings: 将要处理的minion id字符串; :param action: 将要进行的处理,如接受、拒绝、删除; :return: {"return": [{"tag": "salt/wheel/20160322171740805129", "data": {"jid": "20160322171740805129", "return": {}, "success": true, "_stamp": "2016-03-22T09:17:40.899757", "tag": "salt/wheel/20160322171740805129", "user": "zhaogb", "fun": "wheel.key.delete"}}]} ''' func = 'key.' + action params = {'client': 'wheel', 'fun': func, 'match': keystrings} obj = urllib.urlencode(params) content = self.postRequest(obj) ret = content['return'][0]['data']['success'] return ret def acceptKeys(self, keystrings): ''' 接受Minion发过来的key; :return: ''' params = {'client': 'wheel', 'fun': 'key.accept', 'match': keystrings} obj = urllib.urlencode(params) content = self.postRequest(obj) ret = content['return'][0]['data']['success'] return ret def deleteKeys(self, keystrings): ''' 删除Minion keys; :param node_name: :return: ''' params = {'client': 'wheel', 'fun': 'key.delete', 'match': keystrings} obj = urllib.urlencode(params) content = self.postRequest(obj) ret = content['return'][0]['data']['success'] return ret
3)、views.py
# -*- coding: utf-8 -*-from __future__ import unicode_literalsfrom django.shortcuts import renderfrom django.shortcuts import HttpResponse,HttpResponseRedirect,render_to_responsefrom models import *from saltapi import salt_apifrom django.http import JsonResponseimport jsondef index(request): accect = [] context = accect_cmd.objects.values() for i in context: accect.append(i["command"]) if request.method == "POST": key = request.POST.get('key') cmd = request.POST.get('cmd') if cmd.split( )[0] in accect: spi = salt_api.SaltAPI('https://ip:8000', 'username', 'password') result2 = spi.masterToMinionContent(key, 'cmd.run', cmd) return JsonResponse(result2, safe=False) else: data = {key:"请检查命令是否正确或命令超权限,请联系管理员!"} return JsonResponse(data, safe=False) else: return render_to_response('index.html')
4)、models.py
# -*- coding: utf-8 -*-from __future__ import unicode_literalsfrom django.db import models# Create your models here.class accect_cmd(models.Model): command = models.CharField(max_length=50, unique=True, verbose_name=u'命令') status = models.CharField(max_length=20, verbose_name=u'状态') def __unicode__(self): return u'{0} {1}'.format(self.command, self.status)class SaltReturns(models.Model): fun = models.CharField(max_length=50) jid = models.CharField(max_length=255) return_field = models.TextField(db_column='return') success = models.CharField(max_length=10) full_ret = models.TextField() alter_time = models.DateTimeField() class Meta: managed = False db_table = 'salt_returns' def __unicode__(self): return u'%s %s %s' % (self.jid, self.id, self.return_field)class record(models.Model): time = models.DateTimeField(u'时间', auto_now_add=True) comment = models.CharField(max_length=128, blank=True, default='', null=True, verbose_name=u"记录") def __unicode__(self): return u'%s %s' % (self.time, self.comment)
5)、index.html
salt平台
五、效果
1)、单个key执行
2)、多个key执行
3)、当命令不被许可时:
六、总结
写的比较简陋,而且现在这个版本并不支持类似于192.168.1.1+,192.168.1.*这种正则匹配,后续会继续增加。
命令
结果
页面
utf-8
处理
代码
字符
字符串
方式
框架
检查
平台
简陋
危险
主机
人员
内容
前端
单个
参数
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
emobile7登陆服务器是
网页影像服务器在哪里
数据库为什么会出现范式
深信服工业网络安全进去黑名单
浙江什么是少儿编程平台软件开发
景德镇主机服务器哪里比较好
永州正规软件开发价格
网络安全检测包括
方舟为什么加入不了别人的服务器
宁河区全过程网络技术答疑解惑
黑龙江无纸化会议系统软件开发
广东综合软件开发价格多少
食药监官总局数据库
三亚市公安局网络安全
服务器连接数据库异常原因
联想st550服务器如何启动
查询数据库中所有的表
ffan网络安全
萤石云服务器地址在哪里
wow服务器ip
数据库中间有三条线
数据库建库的技术要求参数
大学生网络安全宣传月主题
东莞软件开发公司排名
数据库安全售后
大数据库技术PPT
触犯刑法的人从事网络安全
链接数据库的php
奶块怎么成为服务器管理员
手机服务器在那里找