上篇记录了 saltstack 的安装与配置和简单的使用,但是你会发现基本所有操作,都需要登录到 master机上进行命令行操作,虽然命令行才是最强大的,但是对于新手和入门时的学习使用和管理非常不友好。
然而 salt 已经为我们想到了,下面将为 saltstack 配置一个 web 界面,通过 web 界面来实现一些管理功能,由于 saltstack 官方本身时没有 web 界面的。

 



一、环境准备

系统为 centos7.2,python 版本为2.7

安装 salt-api

[root@V1 ~]# yum install -y salt-api



二、具体配置

添加用户,用户 api 认证

[root@V1 ~]# useradd -M Amos

创建master的配置文件目录

[root@V1 ~]# mkdir /etc/salt/master.d

添加 api 的配置文件,同来配置 api 接口服务的端口和一些设定

[root@V1 ~]# cat /etc/salt/master.d/api.conf
rest_cherrypy:
port: 8000
debug: True
#ssl_crt: /etc/pki/tls/certs/localhost.crt
#ssl_key: /etc/pki/tls/certs/localhost.key
disable_ssl: true

添加 eauth.conf 认证配置文件

[root@V1 ~]# cat /etc/salt/master.d/eauth.conf 
external_auth:
pam:
saltapi:
- .*
- '@wheel'
- '@runner'

Amos 登陆用户名,下面为权限设置,可以根据用户自定义不同的权限。上述为全部权限。

启动 salt-api 服务,并查看运行状态

[root@V1 ~]# systemctl start salt-api
[root@V1 ~]#
[root@V1 ~]# systemctl status salt-api
● salt-api.service - The Salt API
Loaded: loaded (/usr/lib/systemd/system/salt-api.service; disabled; vendor preset: disabled)
Active: active (running) since Tue 2018-07-03 13:39:00 CST; 4s ago
Main PID: 1688 (salt-api)
Tasks: 107
Memory: 32.9M
CGroup: /system.slice/salt-api.service
├─1688 /usr/bin/python /usr/bin/salt-api
└─1695 /usr/bin/python /usr/bin/salt-api

Jul 03 13:39:00 PaulV1 salt-api[1688]: [03/Jul/2018:13:39:00] ENGINE Listening for SIGTERM.
Jul 03 13:39:00 PaulV1 salt-api[1688]: [03/Jul/2018:13:39:00] ENGINE Listening for SIGUSR1.
Jul 03 13:39:00 PaulV1 salt-api[1688]: [03/Jul/2018:13:39:00] ENGINE Bus STARTING
Jul 03 13:39:00 PaulV1 salt-api[1688]: [WARNING ] CherryPy Checker:
Jul 03 13:39:00 PaulV1 salt-api[1688]: 'log_file' is obsolete. Use 'log.error_file' instead.
Jul 03 13:39:00 PaulV1 salt-api[1688]: section: [saltopts]
Jul 03 13:39:00 PaulV1 salt-api[1688]: [03/Jul/2018:13:39:00] ENGINE Started monitor threa...r'.
Jul 03 13:39:00 PaulV1 salt-api[1688]: [03/Jul/2018:13:39:00] ENGINE Started monitor threa...r'.
Jul 03 13:39:01 PaulV1 salt-api[1688]: [03/Jul/2018:13:39:00] ENGINE Serving on 0.0.0.0:8000
Jul 03 13:39:01 PaulV1 salt-api[1688]: [03/Jul/2018:13:39:01] ENGINE Bus STARTED
Hint: Some lines were ellipsized, use -l to show in full.

OK,到此,salt-api 服务启动,可以查看下端口,是否已经监听 8000 端口。

[root@V1 ~]# netstat -antlp|grep 8000
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 1695/python

查看网页内容显示如下

[root@V1 ~]# curl 127.0.0.1:8000
{"clients": ["_is_master_running", "local", "local_async", "local_batch", "runner", "runner_async", "ssh", "ssh_async", "wheel", "wheel_async"], "return": "Welcome"}

然后建立用户进行 pam 认证登录。

useradd -m saltapi                      # 建立账户
echo saltapi |passwd --stdin saltapi # 更新密码

尝试通过 pam 与 minion 进行连接

[root@V1 ~]# salt -a pam '*' test.ping
[DEBUG ] Configuration file path: /root/.saltrc
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[DEBUG ] Reading configuration from /etc/salt/master
[DEBUG ] Including configuration from '/etc/salt/./master.d/api.conf'
[DEBUG ] Reading configuration from /etc/salt/./master.d/api.conf
[DEBUG ] Including configuration from '/etc/salt/./master.d/eauth.conf'
[DEBUG ] Reading configuration from /etc/salt/./master.d/eauth.conf
[DEBUG ] Using cached minion ID from /etc/salt/minion_id: PaulV1
[DEBUG ] Reading configuration from /root/.saltrc
[DEBUG ] MasterEvent PUB socket URI: /var/run/salt/master/master_event_pub.ipc
[DEBUG ] MasterEvent PULL socket URI: /var/run/salt/master/master_event_pull.ipc
[DEBUG ] LazyLoaded pam.auth
username: saltapi
password:
[DEBUG ] Initializing new AsyncZeroMQReqChannel for (u'/etc/salt/pki/master', u'PaulV1_master', u'tcp://xxx.xxx.xxx.xxx:4506', u'clear')
[DEBUG ] Connecting the Minion to the Master URI (for the return server): tcp://xxx.xxx.xxx.xxx:4506
[DEBUG ] Trying to connect to: tcp://xxx.xxx.xxx.xxx:4506
[DEBUG ] Initializing new IPCClient for path: /var/run/salt/master/master_event_pub.ipc
[DEBUG ] LazyLoaded local_cache.get_load
[DEBUG ] Reading minion list from /var/cache/salt/master/jobs/e9/8204414907fdfdbca4b1975501eb10ae6204a34234d5ab7acb22ae0024c169/.minions.p
[DEBUG ] get_iter_returns for jid 20180705114214068068 sent to set(['master', 'client-zyy']) will timeout at 11:42:19.082920
[DEBUG ] jid 20180705114214068068 return from client-zyy
[DEBUG ] return event: {u'client-zyy': {u'jid': u'20180705114214068068', u'retcode': 0, u'ret': True}}
[DEBUG ] LazyLoaded nested.output
client-zyy:
True
[DEBUG ] jid 20180705114214068068 return from master
[DEBUG ] return event: {u'master': {u'jid': u'20180705114214068068', u'retcode': 0, u'ret': True}}
[DEBUG ] LazyLoaded nested.output
master:
True
[DEBUG ] jid 20180705114214068068 found all minions set([u'master', u'client-zyy'])

从信息中可以看出是成功的,这里因为设置了 debug 模式,所以展现了很多信息,如果出现认证失败的话,一般为401,可以参照 ​​saltstack获取token时报错401​​ 排除问题。

 



三、获取 token 和执行 module



3.1 获取 token

Headers 里面是用来存放 headers 的信息的 Body 里面来存放数据的,常用的 data 数据就是 x-www-form-url encoded form-data 是用来存放页面 form 表单数据的 只要 salt-api 不重启,token 就不会过期,salt-api 重启以后,token 就会过期。



1)使用 curl

[root@V1 ~]# curl -X POST -k http://127.0.0.1:8000/login -d username='saltapi' -d password='saltapi' -d eauth='pam' |python -mjson.tool 
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 240 100 197 100 43 6055 1321 --:--:-- --:--:-- --:--:-- 6156
{
"return": [
{
"eauth": "pam",
"expire": 1530881436.314184,
"perms": [
".*",
"@wheel",
"@runner"
],
"start": 1530838236.314184,
"token": "70b01a990ad722cea357ee73f847ad5edd15762c",
"user": "saltapi"
}
]
}



2)使用 postman



a. json 格式

saltstack 的 api_PAM



b. yaml 格式

在 a 点获取到的 json 格式的基础上,在 headers 添加如下内容,即可获取到 yaml 格式

saltstack 的 api_CherryPy_02



3.2 配置证书

依赖关系:CherryPy Python模块

值得注意的是 CherryPy 版本 (3.2.5-3.7.x) 有一个已知的 SSL 跟踪。 请使用 3.2.3 版本或最新的版本。



1)安装 PyOpenSSL

[root@V1 ~]# pip install PyOpenSSL
Looking in indexes: http://mirrors.aliyun.com/pypi/simple/
Requirement already satisfied: PyOpenSSL in /usr/lib64/python2.7/site-packages (18.0.0)
Requirement already satisfied: cryptography>=2.2.1 in /usr/lib64/python2.7/site-packages (from PyOpenSSL) (2.2.2)
Requirement already satisfied: six>=1.5.2 in /usr/lib/python2.7/site-packages (from PyOpenSSL) (1.11.0)
Requirement already satisfied: idna>=2.1 in /usr/lib/python2.7/site-packages (from cryptography>=2.2.1->PyOpenSSL) (2.6)
Requirement already satisfied: cffi>=1.7; platform_python_implementation != "PyPy" in /usr/lib64/python2.7/site-packages (from cryptography>=2.2.1->PyOpenSSL) (1.11.5)
Requirement already satisfied: enum34; python_version < "3" in /usr/lib/python2.7/site-packages (from cryptography>=2.2.1->PyOpenSSL) (1.1.6)
Requirement already satisfied: asn1crypto>=0.21.0 in /usr/lib/python2.7/site-packages (from cryptography>=2.2.1->PyOpenSSL) (0.24.0)
Requirement already satisfied: ipaddress; python_version < "3" in /usr/lib/python2.7/site-packages (from cryptography>=2.2.1->PyOpenSSL) (1.0.16)
Requirement already satisfied: pycparser in /usr/lib/python2.7/site-packages (from cffi>=1.7; platform_python_implementation != "PyPy"->cryptography>=2.2.1->PyOpenSSL) (2.18)

上述显示要求已经满足。



2)更新 cherrypy

[root@V1 salt]# pip install --upgrade cherrypy
Looking in indexes: http://mirrors.aliyun.com/pypi/simple/
Collecting cherrypy
Downloading http://mirrors.aliyun.com/pypi/packages/2b/ea/1726f07c12a8e21d9e776fbb860a53cca689504900fffc0d09c985c6c854/CherryPy-16.0.2-py2.py3-none-any.whl (421kB)
100% |████████████████████████████████| 430kB 2.1MB/s
Collecting portend>=2.1.1 (from cherrypy)
Downloading http://mirrors.aliyun.com/pypi/packages/81/43/21afd5914b74d4271184ee76f4093b45aa6a580dc6627d72dfc33664c6ac/portend-2.3-py2.py3-none-any.whl
Collecting six>=1.11.0 (from cherrypy)
Downloading http://mirrors.aliyun.com/pypi/packages/67/4b/141a581104b1f6397bfa78ac9d43d8ad29a7ca43ea90a2d863fe3056e86a/six-1.11.0-py2.py3-none-any.whl
Collecting cheroot>=6.2.4 (from cherrypy)
Downloading http://mirrors.aliyun.com/pypi/packages/89/18/6e88f695e96eb9c69809bf3c01b5594ac8e6dc2ef64b9c4275a1943fb247/cheroot-6.3.2.post0-py2.py3-none-any.whl (67kB)
100% |████████████████████████████████| 71kB 3.0MB/s
Collecting tempora>=1.8 (from portend>=2.1.1->cherrypy)
Downloading http://mirrors.aliyun.com/pypi/packages/05/1e/7ebc487798b6762438a79eabdc90d62677efc38258dcbacf409d2721f0a4/tempora-1.12-py2.py3-none-any.whl
Collecting backports.functools-lru-cache (from cheroot>=6.2.4->cherrypy)
Downloading http://mirrors.aliyun.com/pypi/packages/03/8e/2424c0e65c4a066e28f539364deee49b6451f8fcd4f718fefa50cc3dcf48/backports.functools_lru_cache-1.5-py2.py3-none-any.whl
Collecting more-itertools>=2.6 (from cheroot>=6.2.4->cherrypy)
Downloading http://mirrors.aliyun.com/pypi/packages/9e/92/d05d8679c3bcaa263169aa47de660080df36d35697855515745657c1ba78/more_itertools-4.2.0-py2-none-any.whl (45kB)
100% |████████████████████████████████| 51kB 46.0MB/s
Collecting pytz (from tempora>=1.8->portend>=2.1.1->cherrypy)
Downloading http://mirrors.aliyun.com/pypi/packages/30/4e/27c34b62430286c6d59177a0842ed90dc789ce5d1ed740887653b898779a/pytz-2018.5-py2.py3-none-any.whl (510kB)
100% |████████████████████████████████| 512kB 58.1MB/s
Installing collected packages: six, pytz, tempora, portend, backports.functools-lru-cache, more-itertools, cheroot, cherrypy
Found existing installation: six 1.9.0
Uninstalling six-1.9.0:
Successfully uninstalled six-1.9.0
Found existing installation: CherryPy 3.6.0
Uninstalling CherryPy-3.6.0:
Successfully uninstalled CherryPy-3.6.0
Successfully installed backports.functools-lru-cache-1.5 cheroot-6.3.2.post0 cherrypy-16.0.2 more-itertools-4.2.0 portend-2.3 pytz-2018.5 six-1.11.0 tempora-1.12



3)生成证书新增配置

使用 create_self_signed_cert()执行函数生成自签名证书。

[root@V1 salt]# salt-call tls.create_self_signed_cert
local:
Created Private Key: "/etc/pki/tls/certs/localhost.key." Created Certificate: "/etc/pki/tls/certs/localhost.crt."

新增配置

[root@V1 ~]# cat /etc/salt/master.d/api.conf 
rest_cherrypy:
port: 8000
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/certs/localhost.key



4)重启服务

[root@V1 salt]# systemctl restart salt-master
[root@V1 salt]# systemctl restart salt-api



5)使用 https 登录

[root@V1 ~]# curl -X POST -k https://127.0.0.1:8000/login -d username='saltapi' -d password='saltapi' -d eauth='pam' |python -mjson.tool
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 240 100 197 100 43 1632 356 --:--:-- --:--:-- --:--:-- 1628
{
"return": [
{
"eauth": "pam",
"expire": 1530887446.957553,
"perms": [
".*",
"@wheel",
"@runner"
],
"start": 1530844246.957552,
"token": "64fe59768432d62e5a5cd1601f70815ace1b72d3",
"user": "saltapi"
}
]
}



3.3 获取执行 module

在成功登录并且获取到 token 之后,我们就可以通过 token 对 minion 端执行一些操作。

首先,我们将 token 值放到 headers

saltstack 的 api_Saltstack_03

然后在 body 中填写需要传入的参数

saltstack 的 api_Saltstack_04

client:对应 local 本地

tgt:表示具体 minion 或分组

fun:模块或自定义函数

arg:需要操作的命令

 

 

 

 



参考资料

1. ​​Saltstack系列3:Saltstack常用模块及API​

2. ​​salt的api学习记录--salt命令的执行过程​

3. ​​saltstack-api使用详解​

4. ​​Salt-API入门指北​

5. ​​Salt-API安装配置及使用​

6. ​​saltstack的教程、例子、资料​

7. ​​saltstack自动化运维​

8. ​​运维工具SaltStack简介​

9. ​​ centos7.2 saltstack配置web界面saltshaker​

10. ​​Salt-API won't listen on https?​

11. ​​REST_CHERRYPY​

12. ​​SSL not working​