salt-api时saltstack官方提供的一个REST API格式的项目,使salt与第三方系统集成变的尤为简单,下面来介绍一下如何配置salt-api与如何使用salt-api获取想要的信息。
安装
1、在master上面安装salt-api
yum install salt-api -y
2、出与安全考虑,官方建议使用https协议,因为salt eauth 身份验证凭证将通过线路发送,因此我们需要安装pyOpenSSL
yum install pyOpenSSL -y
3、自签名证书,生产环境中我们可以购买证书
执行:salt-call --local tls.create_self_signed_cert
local:
Created Private Key: "/etc/pki/tls/certs/localhost.key." Created Certificate: "/etc/pki/tls/certs/localhost.crt."
4、添加api配置到salt-master配置文件
cd /e tc/salt/master.d
vim api.conf
写入:
rest_cherrypy:
host: 172.25.66.1
port: 8000
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/certs/localhost.key
5、创建saltpai用户,并设置密码
6、在slat-master配置文件中添加验证,并且在include目录中创建auth.conf文件
cd /etc/salt/master.d
vim auth.conf
写入:
external_auth:
pam:
saltapi:
- .*
- '@wheel'
- '@runner'
- '@jobs'
7、重启master并且启动salt-api
8、查看salt-api端口
使用
9、验证salt-api服务,并且获取token(salt-api重启后token会失效,需要重新获取)
curl -sSk https://172.25.66.1:8000/login \
> -H 'Accept: application/x-yaml' \
> -d username='saltapi' \
> -d password='saltapi' \
> -d eauth='pam'
return:
- eauth: pam
expire: 1559314837.2068679
perms:
- .*
- '@wheel'
- '@runner'
- '@jobs'
start: 1559271637.2068679
token: 7d9c0982294905a896d9035a9130db055b9d81a6
user: saltapi
10、通过slat-api执行test.ping测试master与minion的连通性
curl -sSk https://172.25.66.1:8000 \
> -H 'Accept: application/x-yaml' \ # 以yaml格式输出
> -H 'X-Auth-Token: 7d9c0982294905a896d9035a9130db055b9d81a6' \
> -d client=local \
> -d tgt='*' \ # 测试所有minion
> -d fun=test.ping
11、使用salt-api执行cmd.run执行minion中的命令
curl -sSk https://172.25.66.1:8000 \
> -H 'Accept: application/x-yaml' \
> -H 'X-Auth-Token: 7d9c0982294905a896d9035a9130db055b9d81a6' \
> -d client=local \
> -d tgt='*' \
> -d fun='cmd.run' -d arg='date'
12、通过salt-api执行状态模块(通过salt-api向minion推送脚本安装服务)
我们向server4中推送apache服务,使用我们之前写好的apache.sls脚本
curl -sSk https://172.25.66.1:8000 \
> -H 'Accept:application/x-yaml' \
> -H 'X-Auth-Token:ef9ad72a71071a4db893783441b98d3ab8e2b0d4' \
> -d tgt='*' \
> -d client=local \
> -d fun='state.sls' \
> -d arg='httpd.apache'
13、以json格式输出
curl -sSk https://172.25.66.1:8000 \
> -H 'Accept:application/json' \
> -H 'X-Auth-Token:ef9ad72a71071a4db893783441b98d3ab8e2b0d4' \
> -d client=local \
> -d tgt='*' \
> -d fun='cmd.run' \
> -d arg='w'
14、利用salt-api获取grains信息
curl -sSk https://172.25.66.1:8000/minions/server2 \
> -H 'Accept:application/x-yaml' \
> -H 'X-Auth-Token:ef9ad72a71071a4db893783441b98d3ab8e2b0d4'
15、使用python脚本请求salt-api
# -*- coding: utf-8 -*-
import urllib2,urllib
import time
try:
import json
except ImportError:
import simplejson as json
class SaltAPI(object):
__token_id = ''
def __init__(self,url,username,password):
self.__url = url.rstrip('/')
self.__user = username
self.__password = password
def token_id(self):
''' user login and get token id '''
params = {'eauth': 'pam', 'username': self.__user, 'password': self.__password}
encode = urllib.urlencode(params)
obj = urllib.unquote(encode)
content = self.postRequest(obj,prefix='/login')
try:
self.__token_id = content['return'][0]['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 list_all_key(self):
params = {'client': 'wheel', 'fun': 'key.list_all'}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
minions = content['return'][0]['data']['return']['minions']
minions_pre = content['return'][0]['data']['return']['minions_pre']
return minions,minions_pre
def delete_key(self,node_name):
params = {'client': 'wheel', 'fun': 'key.delete', 'match': node_name}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
ret = content['return'][0]['data']['success']
return ret
def accept_key(self,node_name):
params = {'client': 'wheel', 'fun': 'key.accept', 'match': node_name}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
ret = content['return'][0]['data']['success']
return ret
def remote_noarg_execution(self,tgt,fun):
''' Execute commands without parameters '''
params = {'client': 'local', 'tgt': tgt, 'fun': fun}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
ret = content['return'][0][tgt]
return ret
def remote_execution(self,tgt,fun,arg):
''' Command execution with parameters '''
params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
ret = content['return'][0][tgt]
return ret
def target_remote_execution(self,tgt,fun,arg):
''' Use targeting for remote execution '''
params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg, 'expr_form': 'nodegroup'}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
jid = content['return'][0]['jid']
return jid
def deploy(self,tgt,arg):
''' Module deployment '''
params = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
return content
def async_deploy(self,tgt,arg):
''' Asynchronously send a command to connected minions '''
params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
jid = content['return'][0]['jid']
return jid
def target_deploy(self,tgt,arg):
''' Based on the node group forms deployment '''
params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'}
obj = urllib.urlencode(params)
self.token_id()
content = self.postRequest(obj)
jid = content['return'][0]['jid']
return jid
def main():
sapi = SaltAPI(url='https://172.25.66.1:8000',username='saltapi',password='saltapi')
sapi.token_id()
print sapi.list_all_key() # 打印master中所有已经获得key的minion
#sapi.delete_key('test-01')
#sapi.accept_key('test-01')
sapi.deploy('*','httpd.apache') # 调用salt-api向所有节点推送apache.sls批量安装apache
#print sapi.remote_noarg_execution('test-01','grains.items')
if __name__ == '__main__':
main()
16、执行python脚本
17、我们将server1中的httpd服务卸载,然后重新执行saltapi.py,查看httpd服务是否安装