SaltApi安装使用

Salt-API安装配置及使用

SaltStack 官方提供有REST API格式的 salt-api 项目,将使Salt与第三方系统集成变得尤为简单。本文讲带你了解如何安装配置Salt-API, 如何利用Salt-API获取想要的信息。
具体使用请参考:salt-api手册

环境说明

  • 操作系统环境: CentOS 6.4/ Centos 7
  • Salt Master/Minion版本: 0.17.2, Master IP地址为172.25.254.135, 用于本次测试的Minion ID为 minion.example.com

实施

安装

  • 7系列
1
2
yum install https://repo.saltstack.com/yum/redhat/salt-repo-latest-1.el7.noarch.rpm
yum install salt-master
  • 6系列
1
2
3
4
5
6
安装salt-api
pip install salt-api
# 下载服务维护脚本
wget https://raw.github.com/saltstack/salt-api/develop/pkg/rpm/salt-api -O /etc/init.d/salt-api
chmod +x /etc/init.d/salt-api
chkconfig salt-api on

配置Salt-API

生成自签名证书(用于ssl)

1
2
3
4
5
6
cd /etc/pki/tls/certs
# 生成自签名证书, 过程中需要输入key密码及RDNs
make testcert
cd /etc/pki/tls/private/
# 解密key文件,生成无密码的key文件, 过程中需要输入key密码,该密码为之前生成证书时设置的密码
openssl rsa -in localhost.key -out salt_nopass.key

Salt-API配置

  • 创建用于salt-api的用户
1
2
useradd -M -s /sbin/nologin salt
echo "salt" | passwd salt —stdin
  • 配置eauth, /etc/salt/master.d/eauth.conf
1
2
3
4
5
6
external_auth:
pam:
salt: #此处的用户与上述创建的用户一致
- .*
- '@wheel'
- '@runner'
  • 配置Salt-API, /etc/salt/master.d/api.conf
1
2
3
4
rest_cherrypy:
port: 8000 #开放端口
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/private/salt_nopass.key
  • 启动Salt-API

service salt-api start

Salt-API使用

  • 使用自带的curl

Login

  • 请求
1
2
3
4
curl -k https://172.25.254.135:8000/login -H "Accept: application/x-yaml" \
-d username='salt' \
-d password='salt' \
-d eauth='pam'
  • 返回
1
2
3
4
5
6
7
8
9
10
return:
- eauth: pam
expire: 1470786521.466763
perms:
- .*
- '@wheel'
- '@runner'
start: 1470743321.466762
token: f59484ca66f52173fb34742fc014f7dc5b027bdd
user: salt

其中 token 后边的串为认证成功后获取的token串,之后可以不用再次输入密码,直接使用本Token即可

查询Minion的信息

  • Request
1
2
3
curl -k https://172.25.254.135:8000/minions/minion.example.com \
-H "Accept: application/x-yaml" \
-H "X-Auth-Token: f59484ca66f52173fb34742fc014f7dc5b027bdd"

其中 X-Auth-Token 后边的串为之前Login获取到的Token串, 如果请求的URL不包含 minion.example.com ,则请求的为所有Minion的信息

  • Response
1
2
3
4
5
6
7
8
9
10
11
12
return:
- minion.example.com:
SSDs: []
biosreleasedate: 12/10/2013
biosversion: X450LCP.205
cpu_flags:
- fpu
- vme
- de
- pse
- tsc

远程执行模块

  • Request
1
2
3
4
5
6
curl -k https://172.25.254.135:8000/ \
-H "Accept: application/x-yaml" \
-H "X-Auth-Token: f59484ca66f52173fb34742fc014f7dc5b027bdd" \
-d client='local' \
-d tgt='*' \
-d fun='test.ping'
  • Response
1
2
return:
- minion.example.com: true

运行runner

  • Request
1
2
3
4
5
curl -k https://172.25.254.135:8000/ \
-H "Accept: application/x-yaml" \
-H "X-Auth-Token: f59484ca66f52173fb34742fc014f7dc5b027bdd" \
-d client='runner' \
-d fun='manage.status'
  • Response
1
2
3
4
return:
- down: []
up:
- minion.example.com

总结

Salt API几乎涵盖了所有的salt操作,功能强劲,尤其是需要salt和第三方系统集成的场景

背后的原理

学过socket编程的同学都知道,server端接受客户端传送的数据,如果用户输入命令的话,那么调用os.popen(command,mode)等,是可以执行命令的,并且将结果返回给客户端。那么就能完成一个基于socket的远程控制系统。

本地API

saltstack是用python写成,我们可以在安装salt的主机上,通过python调用

  • LocalClient
1
2
3
4
In [1]: import salt.client
In [2]: local = salt.client.LocalClient()
In [3]: local.cmd("*",'cmd.run',['whoami'])
Out[3]: {'minion.example.com': 'root'}
  • Salt Caller
1
2
3
4
5
6
7
8
9
In [1]: import salt.client
In [2]: caller = salt.client.Caller()
In [3]: caller.cmd('test.ping')
Out[3]: True
In [4]: caller.function('test.ping') #早期版本不支持 caller.cmd
Out[4]: True
  • RunnerClient
1
2
3
4
5
6
7
8
9
10
In [6]: import salt.config
In [7]: opts =salt.config.master_config('/etc/salt/master')
In [8]: runner = salt.runner.R
salt.runner.Runner salt.runner.RunnerClient
In [8]: runner = salt.runner.RunnerClient(opts)
In [9]: runner.cmd('jobs.list_jobs',[])
  • 返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
20160809195307041368:
----------
Arguments:
Function:
grains.items
StartTime:
2016, Aug 09 19:53:07.041368
Target:
*
Target-type:
glob
User:
salt
Out[9]:
{'20160809195307041368': {'Arguments': [],
'Function': 'grains.items',
'StartTime': '2016, Aug 09 19:53:07.041368',
'Target': '*',
'Target-type': 'glob',
'User': 'salt'},
'20160809195645164703': {'Arguments': [],
'Function': 'test.ping',
'StartTime': '2016, Aug 09 19:56:45.164703',
'Target': '*',
'Target-type': 'glob',
'User': 'salt'},
'20160809200031579904': {'Arguments': [],
'Function': 'test.ping',
'StartTime': '2016, Aug 09 20:00:31.579904',
'Target': '*',
'Target-type': 'glob',
'User': 'root'},
'20160809200943103937': {'Arguments': ['whoami'],
'Function': 'cmd.run',
'StartTime': '2016, Aug 09 20:09:43.103937',
'Target': '*',
'Target-type': 'glob',
'User': 'root'}}

实现

salt-api 是用 Tornado 封装了一个程式,通过继承tornado.web.RequestHandler,获取传递参数
然后根据参数,调用不同的salt命令,返回结果
简易实现如下

import tornado.ioloop
import tornado.web

class SaltAPI(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")
    def post(self):
        data = simplejson.loads(self.request.body)
        获取数据
        调用 salt
        self.write(ruselt)  
application = tornado.web.Application([
    (r"/", SaltAPI),
])

if __name__ == "__main__":
    application.listen(8000)
    tornado.ioloop.IOLoop.instance().start()

更具体的实现,可以看salt-api源码
地址: salt-api