rest_tornado是基于python tornado框架实现的一个Salt REST API技术方案。
您也可以参考在Github上维护的这一份技术资料:rest_tornado
文章目录
A non-blocking REST API for Salt
依赖于
- tornado Python module
配置方法
所有身份验证均通过Salt的 external auth 外部身份验证系统完成,该系统需要此处未介绍的一些其他配置支持。
为了用salt-master运行rest_tornado,需要将以下内容添加到Salt master配置文件中。
rest_tornado:
# can be any port
port: 8000
# address to bind to (defaults to 0.0.0.0)
address: 0.0.0.0
# socket backlog
backlog: 128
ssl_crt: /etc/pki/api/certs/server.crt
# no need to specify ssl_key if cert and key
# are in one single file
ssl_key: /etc/pki/api/certs/server.key
debug: False
disable_ssl: False
webhook_disable_auth: False
cors_origin: null
Authentication - 身份认证
通过在发送访问请求时传递一个session token来执行认证。 令牌是通过SaltAuthHandler
URL生成的。
令牌可以通过以下两种方式之一发送:
- 包含一个名为
X-Auth-Token
的自定义header。 - 通过Cookie发送。 对于自动处理cookie支持的HTTP客户端(例如浏览器),此选项很方便。
See also:您可以通过
RunSaltAPIHandler
URL绕过会话处理。
CORS - 跨站点请求
rest_tornado支持开箱即用的跨站点HTTP请求。 默认情况下,它是由cors_origin
配置键禁用和控制的。
通过将cors_origin
设置为*
,可以允许所有源的访问请求。
使用下面这个配置,您只能允许一个来源:
rest_tornado:
cors_origin: http://salt.yourcompany.com
您还可以更具体一些,并使用列表仅选择一些允许的来源。 例如:
rest_tornado:
cors_origin:
- http://salt.yourcompany.com
- http://salt-preprod.yourcampany.com
来源的格式为完整URL,如果不是标准格式,则包含scheme和端口。
在这种情况下,rest_tornado将在允许的情况下检查Origin报头是否在允许的列表中。 否则,它将不返回任何内容,从而有效地阻止了源发送的请求。
作为参考,CORS是浏览器使用的一种机制,用于允许(或禁止)来自浏览器的请求来自与salt-api不同的来源。 仅当您计划使用作为Javascript浏览器应用程序开发的Salt客户端时,它才是Authentication的补充和强制性要求。
Usage - 使用方法
将HTTP请求发送到下面介绍的URLs,命令通过该模块被发送到正在运行的Salt master。
内容协商
这个REST 接口可以灵活接受各种数据格式以及返回的格式(例如JSON、YAML、x-www-form-urlencoded)。
- 通过包含Content-Type header头来指定请求正文中的数据格式。
- 使用Accept header头为响应主体指定所需的数据格式。
在POST和PUT请求中发送的数据必须采用lowstate词典列表的格式。这允许在单个HTTP请求中执行多个命令。
lowstate
一个包含各种键的字典,这些键指示Salt运行哪个命令,该命令所在的位置,该命令的任何参数,任何身份验证凭据,要使用的returner返回者等。
Salt在许多地方内部使用lowstate数据格式在函数之间传递命令数据。 Salt还对 LocalClient() Python API接口使用lowstate。
以下示例(JSON格式)使用Salt执行两个命令:
[{
"client": "local",
"tgt": "*",
"fun": "test.fib",
"arg": ["10"]
},
{
"client": "runner",
"fun": "jobs.lookup_jid",
"jid": "20130603122505459265"
}]
Salt API请求中的多个命令将串行执行,并且不保证所有命令都将运行。 这意味着,如果test.fib
(来自上面的示例)发生异常,则API仍将执行“ jobs.lookup_jid”
。
对这些lowstate状态的响应是包含返回数据的字典的有序列表,yaml响应可能类似于:
- ms-1: true
ms-2: true
- ms-1: foo
ms-2: bar
如果在执行命令时发生异常,则该lowstate状态的返回将是一个字符串,例如,如果没有minions与第一个lowstate状态匹配,我们将得到如下返回:
- No minions matched the target. No command was sent, no jid was assigned.
- ms-1: true
ms-2: true
x-www-form-urlencoded
在请求正文中发送JSON或YAML是简单且最灵活的,此外还支持以urlencode格式发送数据(有几个事项需要注意)。 它是HTML表单、许多JavaScript库和curl命令的默认格式。
例如,运行salt'*'test.ping
的管理命令相当于在HTTP请求正文中发送fun=test.ping&arg&client=local&tgt=*
的效果。
注意事项:
- 每个HTTP请求只能发送一个命令。
- 重复使用
arg
参数时将导致这些参数组合到一个列表中。
注意,一些流行的框架和语言(特别是jQuery,PHP和Ruby on Rails)会自动将空括号附加到重复的参数上。 例如,arg=one
,arg=two
将作为arg[]=one
, arg[]=two
发送。 这种使用方法是不支持的,请使用JSON或YAML。
A Websockets add-on to saltnado
依赖于
- tornado Python module
为了启用 saltnado_websockets 功能,你需要在 saltnado的配置段落中,增加 websockets: True
的配置。
rest_tornado:
# can be any port
port: 8000
ssl_crt: /etc/pki/api/certs/server.crt
# no need to specify ssl_key if cert and key
# are in one single file
ssl_key: /etc/pki/api/certs/server.key
debug: False
disable_ssl: False
websockets: True
all_events
可以使用一个websocket连接将Salt的事件总线上的所有“实时”事件对外暴露出来。 应该注意的是,这里的“实时”是指一旦有任何与Salt有关的动作发生(更改minions,新的jobs等),这些事件对服务器就是可用的了。 不过,这是在假定客户端能够容忍任何与网络传输相关的延迟的前提之下。 该端点提供的功能类似于/events
端点。
Salt master主机上的事件总线公开了各种各样的东西,特别是在master主机上开始执行管理命令时以及在minions最终返回其结果时。 该URL提供了运行中的Salt基础结构的实时窗口。 使用websocket作为传输机制。
对外暴露一个GET方法以返回websocket连接。 所有请求都应包含一个身份验证令牌。 下面显示了一种获取身份验证令牌的方法。
% curl -si localhost:8000/login \
-H "Accept: application/json" \
-d username='salt' \
-d password='salt' \
-d eauth='pam'
响应结果:
{
"return": [{
"perms": [".*", "@runner", "@wheel"],
"start": 1400556492.277421,
"token": "d0ce6c1a37e99dcc0374392f272fe19c0090cca7",
"expire": 1400599692.277422,
"user": "salt",
"eauth": "pam"
}]
}
在此示例中,返回的令牌为d0ce6c1a37e99dcc0374392f272fe19c0090cca7
,这可以包含在后续的websocket请求中(作为URL的一部分)。
可通过JavaScript轻松地使用事件流:
// Note, you must be authenticated!
// Get the Websocket connection to Salt
var source = new Websocket('wss://localhost:8000/all_events/d0ce6c1a37e99dcc0374392f272fe19c0090cca7');
// Get Salt's "real time" event stream.
source.onopen = function() { source.send('websocket client ready'); };
// Other handlers
source.onerror = function(e) { console.debug('error!', e); };
// e.data represents Salt's "real time" event data as serialized JSON.
source.onmessage = function(e) { console.debug(e.data); };
// Terminates websocket connection and Salt's "real time" event stream on the server.
source.close();
或者使用Python, 例如使用 Python module websocket-client 。 或者是使用 tornado client。
# Note, you must be authenticated!
from websocket import create_connection
# Get the Websocket connection to Salt
ws = create_connection('wss://localhost:8000/all_events/d0ce6c1a37e99dcc0374392f272fe19c0090cca7')
# Get Salt's "real time" event stream.
ws.send('websocket client ready')
# Simple listener to print results of Salt's "real time" event stream.
# Look at https://pypi.python.org/pypi/websocket-client/ for more examples.
while listening_to_events:
print ws.recv() # Salt's "real time" event data as serialized JSON.
# Terminates websocket connection and Salt's "real time" event stream on the server.
ws.close()
# Please refer to https://github.com/liris/websocket-client/issues/81 when using a self signed cert
上面的示例显示了如何建立与Salt的websocket连接以及如何通过向websocket客户端发送信号websocket client ready
通知激活Salt的事件流的实时更新。
formatted_events
通过Websocket连接从Salt的事件总线中暴露格式化的 formatted
“real-time”事件。 应该注意的是,这里的“实时”是指一旦发生任何与Salt有关的动作(更改minions,新jobs等),这些事件就可用于服务器了。 但是,这假定客户端能够容忍任何与网络传输相关的延迟。 该端点提供的功能类似于/events端点。
Salt master主机上的事件总线公开了各种各样的东西,特别是在master主机上开始执行管理命令时以及在minions最终返回其结果时。 该URL提供了运行中的Salt基础结构的实时窗口。 使用websocket作为传输机制。
格式化的事件解析原始的“实时”事件流,并维护以下各项的当前视图:
- minions
- jobs
处理minions的更改(例如添加、删除键或断开连接)或处理jobs作业并更新客户端。 由于我们使用salt的状态事件来跟踪minions,因此请启用present_events
并在salt master配置文件中为loop_interval
设置一个较小的值。
暴露了一个GET方法以返回websocket连接。 所有请求都应包含一个身份验证令牌。 下面显示了一种获取身份验证令牌的方法。
% curl -si localhost:8000/login \
-H "Accept: application/json" \
-d username='salt' \
-d password='salt' \
-d eauth='pam'
响应结果:
{
"return": [{
"perms": [".*", "@runner", "@wheel"],
"start": 1400556492.277421,
"token": "d0ce6c1a37e99dcc0374392f272fe19c0090cca7",
"expire": 1400599692.277422,
"user": "salt",
"eauth": "pam"
}]
}
在此示例中,返回的令牌为d0ce6c1a37e99dcc0374392f272fe19c0090cca7
,并且可以包含在后续的websocket请求中(作为URL的一部分)。
可通过JavaScript轻松使用事件流:
// Note, you must be authenticated!
// Get the Websocket connection to Salt
var source = new Websocket('wss://localhost:8000/formatted_events/d0ce6c1a37e99dcc0374392f272fe19c0090cca7');
// Get Salt's "real time" event stream.
source.onopen = function() { source.send('websocket client ready'); };
// Other handlers
source.onerror = function(e) { console.debug('error!', e); };
// e.data represents Salt's "real time" event data as serialized JSON.
source.onmessage = function(e) { console.debug(e.data); };
// Terminates websocket connection and Salt's "real time" event stream on the server.
source.close();
或者是使用 Python, 例如使用 Python module websocket-client ,或者使用 tornado client。
# Note, you must be authenticated!
from websocket import create_connection
# Get the Websocket connection to Salt
ws = create_connection('wss://localhost:8000/formatted_events/d0ce6c1a37e99dcc0374392f272fe19c0090cca7')
# Get Salt's "real time" event stream.
ws.send('websocket client ready')
# Simple listener to print results of Salt's "real time" event stream.
# Look at https://pypi.python.org/pypi/websocket-client/ for more examples.
while listening_to_events:
print ws.recv() # Salt's "real time" event data as serialized JSON.
# Terminates websocket connection and Salt's "real time" event stream on the server.
ws.close()
# Please refer to https://github.com/liris/websocket-client/issues/81 when using a self signed cert
上面的示例显示了如何建立与Salt的websocket连接以及如何通过向websocket客户端发送信号通知激活Salt的事件流的实时更新。
Example responses
Minion信息是由每个相连的minion的ID(mid)作为关键字的字典,还包括每个minion的grains信息。
在响应结果中会随着以下minion事件发送Minion的信息:
- connection drops
- 需要每间隔
loop_interval
秒定期运行一次manage.present
- 需要每间隔
- minion addition
- minon removal
# Not all grains are shown
data: {
"minions": {
"minion1": {
"id": "minion1",
"grains": {
"kernel": "Darwin",
"domain": "local",
"zmqversion": "4.0.3",
"kernelrelease": "13.2.0"
}
}
}
}
Job information
也会被跟踪和发送。
作业信息也是字典,其中每个作业的信息都以salt的jid
作为关键字。
data: {
"jobs": {
"20140609153646699137": {
"tgt_type": "glob",
"jid": "20140609153646699137",
"tgt": "*",
"start_time": "2014-06-09T15:36:46.700315",
"state": "complete",
"fun": "test.ping",
"minions": {
"minion1": {
"return": true,
"retcode": 0,
"success": true
}
}
}
}
}
REST URI Reference
/
salt.netapi.rest_tornado.saltnado.SaltAPIHandler
内置别名。
/login
salt.netapi.rest_tornado.saltnado.SaltAuthHandler
内置别名。
/minions
salt.netapi.rest_tornado.saltnado.MinionSaltAPIHandler
内置别名。
/jobs
salt.netapi.rest_tornado.saltnado.JobsSaltAPIHandler
内置别名。
/run
salt.netapi.rest_tornado.saltnado.RunSaltAPIHandler
内置别名。
/events
salt.netapi.rest_tornado.saltnado.EventsSaltAPIHandler
内置别名。
/hook
salt.netapi.rest_tornado.saltnado.WebhookSaltAPIHandler
内置别名。
来源:https://blog.csdn.net/watermelonbig/article/details/102760508