1.1 salt-api安装
参考博客:https://www.jianshu.com/p/012ccdff93cc
1、介绍
1. saltsatck本身就提供了一套算完整的api,使用 CherryPy 来实现 restful 的 api,供外部的程序调用。
2. salt-api需要安装,然后进行一些配置才可以正常使用
2、安装salt-api,并设置开机启动
yum -y install salt-api pyOpenSSL
systemctl enable salt-api
3、配置自签名证书
cd /etc/pki/tls/certs/
make testcert
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Enter pass phrase: ===> 输入加密短语,这里我使用salt2017 Verifying - Enter pass phrase: ===> 确认加密短语 umask 77 ; /usr/bin/openssl req -utf8 -new -key /etc/pki/tls/private/localhost.key -x509 -days 365 -out /etc/pki/tls/certs/localhost.crt -set_serial 0 Enter pass phrase for /etc/pki/tls/private/localhost.key: ===> 再次输入相同的加密短语 You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:BeiJing Locality Name (eg, city) [Default City]:BeiJing Organization Name (eg, company) [Default Company Ltd]: Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []: Email Address []:
4、解密key文件,生成无密码的key文件
注:过程中需要输入key密码,该密码为之前生成证书时设置的密码
cd /etc/pki/tls/private/
openssl rsa -in localhost.key -out localhost_nopass.key
5、修改文件权限
chmod 755 /etc/pki/tls/certs/localhost.crt
chmod 755 /etc/pki/tls/private/localhost.key
chmod 755 /etc/pki/tls/private/localhost_nopass.key
6、添加用户
注:生产环境请使用密码复杂度高的密码,这里我使用 chnsys@2016
useradd -M -s /sbin/nologin saltapi # 创建用户 saltapi
passwd saltapi # 为用户saltapi设置密码
7、配置salt-api
sed -i '/#default_include/s/#default/default/g' /etc/salt/master
8、创建/etc/salt/master.d/目录
mkdir -p /etc/salt/master.d/
cd /etc/salt/master.d/
touch eauth.conf
touch api.conf
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
external_auth: pam: saltapi: # 用户 - .* # 该配置文件给予saltapi用户所有模块使用权限,出于安全考虑一般只给予特定模块使用权限
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
rest_cherrypy: port: 8001 ssl_crt: /etc/pki/tls/certs/localhost.crt ssl_key: /etc/pki/tls/private/localhost_nopass.key
9、启动salt-api
systemctl restart salt-master
systemctl start salt-api
ps -ef|grep salt-api
netstat -lnput|grep 8001
10、测试获取token
curl -k https://192.168.56.11:8001/login -H "Accept: application/x-yaml" -d username='saltapi' -d password='chnsys@2016' -d eauth='pam'
11、调用test.ping
curl -k https://192.168.56.11:8001/ -H "Accept: application/x-yaml" -H "X-Auth-Token: 87cbb68e0babf3d0ad6b3741795667dbe62b3c11" -d client='local' -d tgt='*' -d fun='test.ping'
1.2 编写python脚本请求salt api接口
1、使用python简单测试接口执行命令
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'junxi' import requests import json try: import cookielib except: import http.cookiejar as cookielib # 使用urllib2请求https出错,做的设置 import ssl context = ssl._create_unverified_context() # 使用requests请求https出现警告,做的设置 from requests.packages.urllib3.exceptions import InsecureRequestWarning requests.packages.urllib3.disable_warnings(InsecureRequestWarning) salt_api = "https://192.168.56.11:8001/" class SaltApi: """ 定义salt api接口的类 初始化获得token """ def __init__(self, url): self.url = url self.username = "saltapi" self.password = "chnsys@2016" self.headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36", "Content-type": "application/json" } self.params = {'client': 'local', 'fun': '', 'tgt': ''} self.login_url = salt_api + "login" self.login_params = {'username': self.username, 'password': self.password, 'eauth': 'pam'} self.token = self.get_data(self.login_url, self.login_params)['token'] self.headers['X-Auth-Token'] = self.token def get_data(self, url, params): send_data = json.dumps(params) request = requests.post(url, data=send_data, headers=self.headers, verify=False) response = request.json() result = dict(response) return result['return'][0] def salt_command(self, tgt, method, arg=None): """远程执行命令,相当于salt 'client1' cmd.run 'free -m'""" if arg: params = {'client': 'local', 'fun': method, 'tgt': tgt, 'arg': arg} else: params = {'client': 'local', 'fun': method, 'tgt': tgt} print '命令参数: ', params result = self.get_data(self.url, params) return result def main(): salt = SaltApi(salt_api) salt_client = '*' salt_test = 'test.ping' result1 = salt.salt_command(salt_client, salt_test) print result1 # 返回结果:{u'linux-node1.example.com': True, u'linux-node2.example.com': True} if __name__ == '__main__': main()
2、使用requests模块获取基本信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#! /usr/bin/env python # -*- coding: utf-8 -*- import requests import json import logging logging.captureWarnings(True) # 屏蔽由于访问https时没有证书警告问题 SALT_BASE_URL = 'https://192.168.56.11:8001/' SALT_USER = 'saltapi' SALT_PWD = 'chnsys@2016' class SaltAPI(object): __token_id = '' def __init__(self): self.__url = SALT_BASE_URL self.__user = SALT_USER self.__password = SALT_PWD def token_id(self): """ 用户登陆和获取token :return: """ params = {'eauth': 'pam', 'username': self.__user, 'password': self.__password} content = self.postRequest(self.__url + '/login', data=params) try: self.__token_id = content[0]['token'] except Exception as e: print '**** Failed to get token, {} ****'.format(str(e)) def postRequest(self, url, data=None): headers = {"X-Auth-Token": self.__token_id} ret = requests.post(url=url, data=data, json='json', headers=headers, verify=False) if ret.status_code == 200: return ret.json()['return'] return ret.text def remote_execution_module(self, tgt, fun, arg): """ 远程执行模块,有参数 :param tgt: minion list :param fun: 模块 :param arg: 参数 :return: dict, {'minion1': 'ret', 'minion2': 'ret'} """ params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg} self.token_id() return self.postRequest(self.__url, params) def salt_alive(self, tgt): ''' salt主机存活检测 ''' params = {'client': 'local', 'tgt': tgt, 'fun': 'test.ping'} self.token_id() return self.postRequest(self.__url, params) if __name__ == '__main__': salt = SaltAPI() minions_list = [ 'cloud:type', 'cluster:domain', 'cluster:name', 'cpu_model', 'fqdn_ip4', 'hospital:type', 'kernelrelease', 'nodename', 'os', 'osmajorrelease', 'osrelease', 'saltversion', 'serialnumber', 'virtual', 'num_cpus', 'mem_total', 'cloud:region', 'ipv4', ] ret = salt.remote_execution_module('*', 'grains.item', minions_list) print json.dumps(ret, ensure_ascii=False) ''' [{ "linux-node1.example.com": { "osrelease": "7.6.1810", "fqdn_ip4": ["192.168.56.11"], "serialnumber": "VMware-56 4d 26 83 60 7c bb 5a-14 17 6a ab c2 45 f2 7a", "nodename": "linux-node1.example.com", "kernelrelease": "3.10.0-957.1.3.el7.x86_64", "cloud:type": "", "num_cpus": 1, "saltversion": "2018.3.3", "cpu_model": "Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz", "virtual": "VMware", "cluster:domain": "", "cluster:name": "", "osmajorrelease": 7, "hospital:type": "", "cloud:region": "", "os": "CentOS", "ipv4": ["127.0.0.1", "192.168.56.11"], "mem_total": 1819 }, "linux-node2.example.com": { "osrelease": "7.6.1810", "fqdn_ip4": ["192.168.56.12"], "serialnumber": "VMware-56 4d 09 af 9d 33 70 99-e9 7b 6d b2 5a 3b 7f 22", "nodename": "linux-node2.example.com", "kernelrelease": "3.10.0-957.1.3.el7.x86_64", "cloud:type": "", "num_cpus": 1, "saltversion": "2018.3.3", "cpu_model": "Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz", "virtual": "VMware", "cluster:domain": "", "cluster:name": "", "osmajorrelease": 7, "hospital:type": "", "cloud:region": "", "os": "CentOS", "ipv4": ["127.0.0.1", "192.168.56.12"], "mem_total": 1819 } }] '''
3、解决访问无证书https报错:requests.exceptions.SSLError: HTTPSConnectionPool
参考博客:https://blog.csdn.net/qq_31077649/article/details/79013199
1)安装相关模块:
pip install cryptography
pip install pyOpenSSL
pip install certifi
2)关闭证书验证(verify=False)
ret = requests.post(url=url, data=data, json='json', headers=headers, verify=False)
1111111111111111111111111111111