SaltStack netapi模块REST API——rest_tornado

爷,独闯天下 提交于 2019-12-02 12:30:27

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头为响应主体指定所需的数据格式。

POSTPUT请求中发送的数据必须采用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=onearg=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

内置别名。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!