请求流程
服务端 ---> salt-api ---> salt-master ---> salt-minion
参考文章 https://www.jianshu.com/p/012ccdff93cc
1)saltstack安装
在服务器端上安装salt-api和salt-master
yum install -y salt-master salt-api
在客户端上安装salt-minion
yum install -y salt-minion
启动master服务和配置minion且启动服务
systemctl start salt-master
vi /etc/salt/minion
master: 192.168.80.103
systemctl start salt-minion
认证minion
salt-key -L #查看所有机子
salt-key -A #验证所有机子
返回结果是主机是key 内容是value
salt 'kun04' cmd.run 'df -h'
kun04:
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 18G 2.3G 16G 13% /
devtmpfs 482M 0 482M 0% /dev
2)saltapi安装
yum install -y salt-api pyOpenSSL
3)配置自签名证书
cd /etc/pki/tls/certs/
make testcert
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 []:
通过设置的密码用于生成无密码的key文件的
cd /etc/pki/tls/private/
openssl rsa -in localhost.key -out localhost_nopass.key
修改三个密钥的权限
chmod 755 /etc/pki/tls/certs/localhost.crt
private]# chmod 755 /etc/pki/tls/private/localhost.key
private]# chmod 755 /etc/pki/tls/private/localhost_nopass.key
创建用户
useradd -M -s /sbin/nologin saltapi
passwd saltapi
由于在生成环境中root用户权限过大,因此创建saltapi用户来降低权限
4)配置salt-api 并启动服务
vim /etc/salt/master
取消注释
default_include: master.d/*.conf
进入该目录创建两个配置文件
cd /etc/salt/master.d/
vim eauth.conf
external_auth:
pam:
saltapi: # 用户
- .* # 该配置文件给予saltapi用户所有模块使用权限,出于安全考虑一般只给予特定模块使用权限
vim api.conf
rest_cherrypy:
port: 8001
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/private/localhost_nopass.key
systemctl restart salt-master
systemctl start salt-api
查看salt-api是否启动成功
ps -ef |grep salt-api
netstat -lntp |grep 8001
验证是否可以获得token
curl -k https://192.168.80.103:8001/login -H "Accept: application/x-yaml" -d username='saltapi' -d
password='coco0769' -d eauth='pam'
return:
- eauth: pam
expire: 1548297720.710394
perms:
- .*
start: 1548254520.710393
token: 99f92e648d1499adb8fb1a05d4e465b0578b7d7d
user: saltapi
编写python脚本请求salt api接口
python调用salt-api执行命令首先自定义一个类,首先初始化时候获得token,然后使用token认证去请求相应的json文件。
salt命令在shell中使用方式是salt 客户端 方法 参数(例子:salt 'client1' cmd.run 'free -m')。
这里salt命令方法我们已经封装好了,想使用salt的什么方法就传入对应的客户端、方法、参数即可。
#!/usr/bin/env python
# coding:utf-8
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.80.103:8001/"
class SaltApi:
"""
定义salt api接口的类
初始化获得token
"""
def __init__(self, url):
self.url = url
self.username = "saltapi"
self.password = "coco0769"
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).get('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 = 'kun04'
salt_client = '*'
salt_test = 'test.ping'
#salt_method = 'cmd.run'
salt_method = 'grains.get'
#salt_params = 'free -m'
salt_params = 'ip_interfaces'
result1 = salt.salt_command(salt_client, salt_test)
print(result1)
result2 = salt.salt_command(salt_client, salt_method, salt_params)
print(result2)
if __name__ == '__main__':
main()