使用salt-api来搭建salt自动化平台
发表于:2024-12-12 作者:千家信息网编辑
千家信息网最后更新 2024年12月12日,一、介绍通常使用saltstack都是在master的服务器上直接命令操作,这个对于运维人员来说不是什么大事,但是也会有出错的时候,而一旦出错,就会有不可挽回的后果。二、框架这里使用django框架,
千家信息网最后更新 2024年12月12日使用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安全错误
数据库的锁怎样保障安全
数据库的删除数据语句
车载软件开发系统
数据库事务acid
网络安全高中
数据库连接串特殊字符
南京天橙网络技术有限公司
网络安全逆向小说
我想找几个软件开发者
规范督查检查 网络安全
杭州安卓软件开发价钱
嘉定区游戏软件开发流程
朝阳区品牌软件开发优势
怎么用数据库挂单页
php 分布式服务器
linux连接远程数据库
影像编辑服务器
点击微信图标提示服务器错误
服务器安全组未开放
cache数据库国内公司
软件开发课程故事绘本
数据库时间字段
互联网科技帝国
服务器为什么会拒绝请求
信息网络安全教案
亚马逊云服务器 香港
爱加速怎么断开服务器
录播服务器怎么选
我的世界吃鸡服务器名字
服务器数据库数量
两个数据库同步部分