当前位置: 首页 > 工具软件 > CherryPy > 使用案例 >

SaltStack netapi模块REST API——rest_cherrypy

王英彦
2023-12-01

A REST API FOR SALT

截止当前,cherrypy的REST API方案是最为成熟的,也是Salt官方更为推荐使用的一个REST API实现方案。

您也可以参考在Github上维护的这一份技术资料:rest_cherrypy

Install and configuration - 安装与配置

depends - 必需依赖

  • CherryPy Python module.

    注意: 有一个已知的 SSL traceback 功能bug存在于 CherryPy versions 3.2.5 到 3.7.x之间的版本中,请使用版本 3.2.3 或者是最新的 10.x 版本。

optdepends - 可选依赖

  • ws4py Python module for websockets support.

client_libraries - 客户端工具

  • Java: https://github.com/SUSE/salt-netapi-client
  • Python: https://github.com/saltstack/pepper

setup - 安装 REST_CHERRYPY

以下所有步骤均在运行Salt Master守护程序的计算机上执行。 配置则整合进了master配置文件中。

  1. 安装salt-api。 (此步骤在OS和Linux发行版之间有所不同。某些软件包系统有一个分离的软件包,其他软件包系统在主Salt软件包中包含salt-api。确保salt-api --version输出与salt --version输出信息相匹配。)
  2. 安装 CherryPy。(阅读以上部分中的版本使用警告。)
  3. 可选的配置: 生成自签的 SSL 证书。强烈建议使用安全的HTTPS连接,因为Salt eauth身份验证凭据将通过网络发送。
  4. 安装 PyOpenSSL 软件包。
  5. 使用执行模块函数 create_self_signed_cert() 生成一个自签的数据证书。
        salt-call --local tls.create_self_signed_cert
  1. 按照 External Authentication System - 使用外部身份认证系统,编辑master配置以创建至少一个支持外部身份验证的用户或组。
  2. 使用下面一个面向生产环境的示例编辑master配置,以启用rest_cherrypy模块。 (根据需要调整证书路径,或禁用SSL(不推荐!)。
    rest_cherrypy:
      port: 8000
      ssl_crt: /etc/pki/tls/certs/localhost.crt
      ssl_key: /etc/pki/tls/certs/localhost.key
  1. 重启 salt-master 服务进程。
  2. 启动 salt-api 服务进程。

configuration - 配置 REST_CHERRYPY

下面详细介绍了所有可用的配置选项。 这些设置用于配置CherryPy HTTP服务器,在使用外部服务器(例如Apache或Nginx)时不适用。

  • port

    必需配置项。指定webserver的服务端口。

  • host 0.0.0.0

    HTTP服务器侦听的套接字接口。

  • debug False

在开发模式下启动Web服务器。 当底层代码更改时,它将重新加载自身,并输出更多的调试信息。

  • log_access_file

    写入HTTP访问日志的文件的路径。

    New in version 2016.11.0.

  • log_error_file

    写入HTTP错误日志的文件的路径。

    New in version 2016.11.0.

  • ssl_crt

    定义 SSL 证书文件的路径。 (See below)

  • ssl_key

    定义SSL certificate 证书的私钥文件的路径。 (See below)

  • ssl_chain

    (使用PyOpenSSL时是可选的)传递给Context.load_verify_locationsr 的证书链。

  • disable_ssl

    一个禁用SSL的配置项。警告: 你的 Salt 认证信息将会以明文发送!

  • webhook_disable_auth False

Webhook URL默认情况下需要身份验证,但是不能始终将外部服务配置为发送身份验证。 请参阅下文中的Webhook文档以获取有关保护此接口的建议。

  • webhook_url/hook

    配置Webhook入口点的URL端点。

  • thread_pool 100

    定义在线程池中使用的并发线程数。

  • socket_queue_size 30

    指定HTTP连接队列的最大值。

  • expire_responses True

是否检查并杀死超过默认超时时间的HTTP响应。

自2016.11.9,2017.7.3,2018.3.0版本以来已弃用:CherryPy中的expire_responses功能上等同于CherryPy中的timeout_monitor参数,在>=12.0.0的CherryPy版本中不再受支持。

  • max_request_body_size 1048576

    HTTP request 请求允许携带的最大数据。

  • collect_stats False

    检查和报告CherryPy服务器的统计数据。
    报告可以通过访问 /stats URL端点地址获取。

  • stats_disable_auth False

    访问 /stats 端点时不需要提供访问认证信息。

    New in version 2018.3.0.

  • static

    静态HTML/JavaScript/CSS/image资产的文件系统路径。

  • static_path /static

    访问static设置中指定的目录中提供静态资产时使用的URL前缀。

  • enable_sessions True

    启用或禁用所有依赖会话cookie的端点。 这对于执行仅基于headers的身份验证可能很有用。

    New in version 2017.7.0.

  • app index.html

    HTML文件的文件系统路径,它将用作静态文件。 这对于引导单页JavaScript应用程序很有用。

    警告! 如果将此选项设置为自定义Web应用程序,则使用基于cookie的身份验证的任何内容都容易受到XSRF攻击。 建议发送自定义X-Auth-Token标头,并考虑禁用enable_sessions设置。

    Changed in version 2017.7.0: 增加一个 proof-of-concept JavaScript 单页应用。

  • app_path /app

    用于提供在应用程序设置中指定的HTML文件的URL前缀。 这应该是一个不包含斜杠的简单名称。

    指定路径之后的所有路径信息都将被忽略; 这对于使用HTML5历史记录API的应用程序很有用。

  • root_prefix /

    指向应用程序主入口点的URL路径。 这对于从同一URL提供多个应用程序很有用。

Authentication - 认证

通过向每个请求传递会话令牌来执行认证的操作。 令牌是通过名为Login的URL生成的。

令牌可以通过以下两种方式之一发送:作为自定义header或作为会话cookie。 对于支持cookie的客户端,后者要方便得多。

  • 包括一个名为X-Auth-Token属性的自定义header。

    例如,使用curl:

    curl -sSk https://localhost:8000/login \
        -H 'Accept: application/x-yaml' \
        -d username=saltdev \
        -d password=saltdev \
        -d eauth=pam
    

    从输出中复制token令牌值,并将其包含在后续的请求操作中:

    curl -sSk https://localhost:8000 \
        -H 'Accept: application/x-yaml' \
        -H 'X-Auth-Token: 697adbdc8fe971d09ae4c2a3add7248859c87079'\
        -d client=local \
        -d tgt='*' \
        -d fun=test.ping
    
  • 通过Cookie发送。 对于可以自动处理cookie支持的HTTP客户端(例如浏览器),此选项会很方便。

    例如,使用curl:

    # Write the cookie file:
    curl -sSk https://localhost:8000/login \
          -c ~/cookies.txt \
          -H 'Accept: application/x-yaml' \
          -d username=saltdev \
          -d password=saltdev \
          -d eauth=auto
    
    # Read the cookie file:
    curl -sSk https://localhost:8000 \
          -b ~/cookies.txt \
          -H 'Accept: application/x-yaml' \
          -d client=local \
          -d tgt='*' \
          -d fun=test.ping
    

    另外一个在Python中使用 requests类库的例子:

    >>> import requests
    >>> session = requests.Session()
    >>> session.post('http://localhost:8000/login', json={
        'username': 'saltdev',
        'password': 'saltdev',
        'eauth': 'auto',
    })
    <Response [200]>
    >>> resp = session.post('http://localhost:8000', json=[{
        'client': 'local',
        'tgt': '*',
        'fun': 'test.arg',
        'arg': ['foo', 'bar'],
        'kwarg': {'baz': 'Baz!'},
    }])
    >>> resp.json()
    {u'return': [{
        ...snip...
    }]}
    

    See also:你还可以使用 Run URL来传递session会话数据,作为POST数据中的一项键值。

Usage - 用法

该接口直接公开作为Salt的Python API使用。 CLI可用的一切功能也都可以通过Python API实现。 命令是在Salt Master上执行。

根URL(/)类似于RPC,因为它在请求正文中接受有关要执行哪些Salt函数的指令,并且在响应中包含这些函数调用的结果。

例如:

  % curl -sSi https://localhost:8000         -H 'Content-type: application/json'         -d '[{
          "client": "local",
          "tgt": "*",
          "fun": "test.ping"
      }]'
  HTTP/1.1 200 OK
  Content-Type: application/json
  [...snip...]

  {"return": [{"jerry": true}]}

请求主体必须是命令数组。 使用下面这样的工作流程来构建命令:

  1. 选择一个客户端接口
  2. 选择一个功能函数
  3. 填充调用该接口需要提供的其它参数

client字段是对Salt的Python API中使用的主要Python类的引用。详情可以阅读完整的客户端API文档,但简而言之:

  • “local” 使用LocalClient,它向Minions发送命令。等同于salt CLI命令。
  • “runner” 使用RunnerClient,它在Master服务器上调用runner程序模块。等同于使用salt-run CLI命令。
  • “wheel” 使用WheelClient调用Master模块上的wheel模块。Wheel模块没有直接的CLI等效项,但是它们通常管理Master-side端资源,例如状态文件、pillar文件、Salt配置文件,并且key wheel module模块具有与salt-key CLI命令相似的管理功能。

大多数客户端具有诸如同步执行或异步执行之类的变体,以及诸如批处理执行之类的其他变体。请参阅客户端接口的完整列表

每个客户端需要不同的参数,有时具有不同的语法。例如,LocalClient需要tgt参数,因为它将命令转发给Minions,而其他客户端接口则不需要。 LocalClient还使用arg(数组)和kwarg(字典)参数,因为这些值也需要被发送到Minions,并用于在那里执行请求的功能。 RunnerClientWheelClient直接在Master服务器上执行,因此不需要或不接受这些参数。

阅读上面链接的客户端文档中的方法签名,但是希望有一个示例可以帮助说明该概念。这个例子使用Salt执行两个函数-使用LocalClient执行的test.arg execution函数和使用RunnerClient执行的test.arg Runner函数;注意每个命令的结构不同。两者的结果合并并作为一个响应返回。

  % curl -b ~/cookies.txt -sSi localhost:8000         -H 'Content-type: application/json'         -d '
  [
      {
          "client": "local",
          "tgt": "*",
          "fun": "test.arg",
          "arg": ["positional arg one", "positional arg two"],
          "kwarg": {
              "keyword arg one": "Hello from a minion",
              "keyword arg two": "Hello again from a minion"
          }
      },
      {
          "client": "runner",
          "fun": "test.arg",
          "keyword arg one": "Hello from a master",
          "keyword arg two": "Runners do not support positional args"
      }
  ]
  '
  HTTP/1.1 200 OK
  [...snip...]
  {
    "return": [
      {
        "jerry": {
          "args": [
            "positional arg one",
            "positional arg two"
          ],
          "kwargs": {
            "keyword arg one": "Hello from a minion",
            "keyword arg two": "Hello again from a minion",
            [...snip...]
          }
        },
        [...snip; other minion returns here...]
      },
      {
        "args": [],
        "kwargs": {
          "keyword arg two": "Runners do not support positional args",
          "keyword arg one": "Hello from a master"
        }
      }
    ]
  }

另一个例子, 这次使用更常见的功能函数:

  curl -b /tmp/cookies.txt -sSi localhost:8000         -H 'Content-type: application/json'         -d '
  [
      {
          "client": "local",
          "tgt": "*",
          "fun": "state.sls",
          "kwarg": {
              "mods": "apache",
              "pillar": {
                  "lookup": {
                      "wwwdir": "/srv/httpd/htdocs"
                  }
              }
          }
      },
      {
          "client": "runner",
          "fun": "cloud.create",
          "provider": "my-ec2-provider",
          "instances": "my-centos-6",
          "image": "ami-1624987f",
          "delvol_on_destroy", true
      }
  ]
  '
  HTTP/1.1 200 OK
  [...snip...]
  {
    "return": [
      {
        "jerry": {
          "pkg_|-install_apache_|-httpd_|-installed": {
              [...snip full state return here...]
          }
        }
        [...snip other minion returns here...]
      },
      {
          [...snip full salt-cloud output here...]
      }
    ]
  }

Content negotiation - 内容协商

这个REST接口可以灵活接受各种数据格式,以及可以传回的格式(例如JSON,YAML和urlencoded)。

  • 通过包含Content-Type header来指定请求正文中的数据格式。
  • 使用Accept header为响应主体指定所需的数据格式。

对于大多数HTTP请求,我们建议使用JSON格式。 urlencoded数据很简单,不能表示复杂的数据结构 - 而这对于某些Salt命令来说通常是必需的,例如启动使用Pillar数据的状态运行。 Salt的CLI工具可以将在CLI处传递的字符串重新格式化为复杂的数据结构,并且该行为也可以通过salt-api起作用,但这可能很脆弱。因为salt-api可以接受JSON,所以最好仅发送JSON。

下面是发送urlencoded数据的示例:

curl -sSik https://localhost:8000 \
    -b ~/cookies.txt \
    -d client=runner \
    -d fun='jobs.lookup_jid' \
    -d jid='20150129182456704682'

注意:urlencoded数据警告

  • 每个HTTP请求只能发送一个命令。

  • 多次重复arg参数将导致这些参数组合到一个列表中。

    注意,一些流行的框架和语言(特别是jQuery,PHP和Ruby on Rails)会自动将空括号附加到重复的查询字符串参数上。 例如,?foo[]=fooone&foo[]=footwo。,而这是不支持的。请发送?foo=fooone&foo=footwo,或者发送JSON或YAML。

关于使用curl的注意事项

curl的-d标志不会自动对可能影响密码和包含必须编码字符的其他数据的数据进行urlencode。 请改用--data-urlencode标志。 例如。:

curl -ksi http://localhost:8000/login \
-H "Accept: application/json" \
-d username='myapiuser' \
--data-urlencode password='1234+' \
-d eauth='pam'

Performance Expectations and Recommended Usage

性能期望和推荐用法

该模块提供了Salt的Python API的精简包装。 通过rest_cherrypy执行Salt命令直接类似于通过Salt的CLI(也使用Python API)执行Salt命令-它们共享相同的语义、性能特征以及98%的相同代码。 作为一个经验法则:如果您不打算在CLI上执行此操作,请也不要通过此API进行操作。

Long-Running HTTP Connections - 需要长时间运行的HTTP连接

CherryPy服务器是用Python编写的可用于生产环境的线程HTTP服务器。 因为它利用线程池来处理HTTP请求,所以它不适合维护大量并发的同步连接。 在具有默认设置的中型硬件设备上,它应该在大约30到50个并发连接时达到性能顶峰。

这么长时间运行的Salt同步过程也不理想。 像在CLI中一样,每次Salt命令运行都会启动一个实例化自己的LocalClient的进程,该进程实例化自己对Salt事件总线的侦听器,并发出自己的定期saltutil.find_job查询以确定Minion是否仍在运行该命令 。 不完全是轻量级的操作。

Timeouts - 超时

除了上述用于长时间运行的连接的资源开销外,CherryPy服务器,使用的任何HTTP客户端以及介于两者之间的任何硬件(例如代理、网关或负载均衡器)都有常用的HTTP超时语义。 可以将rest_cherrypy配置为不通过expire_responses设置使长响应超时,并且LocalClientRunnerClient都有自己的超时参数,可以将其作为顶级关键字传递:

curl -b /tmp/cookies.txt -sSi localhost:8000         -H 'Content-type: application/json'         -d '
[
    {
        "client": "local",
        "tgt": "*",
        "fun": "test.sleep",
        "kwarg": {"length": 30},
        "timeout": 60
    },
    {
        "client": "runner",
        "fun": "test.sleep",
        "kwarg": {"s_time": 30},
        "timeout": 60
    }
]
'

Best Practices - 最佳实践

考虑到上述长时间运行的操作的性能开销和HTTP超时,使用Salt和salt-api的最有效、最可扩展的方法是使用local_asyncrunner_asyncwheel_async客户端异步运行命令。

运行异步作业可以使LocalClient每秒处理的命令数量增加3倍,而RunnerClient每秒处理的命令数量增加17倍,此外,网络流量和内存需求也要少得多。可以通过/jobs/<jid>端点从Salt的作业缓存中获取作业返回,或者可以使用Salt的Returner系统将其收集到数据存储中。

/events端点专门用于处理长时间运行的HTTP连接,它公开了Salt的事件总线,其中包括作业返回。首先观看此端点,然后再执行异步Salt命令,是使用rest_cherrypy的最轻便和可扩展的方式,同时仍实时接收作业返回。但这要求客户端能够正确处理该工作流的固有异步性。

Performance Tuning - 性能调优

可以使用thread_poolsocket_queue_size设置来增加rest_cherrypy处理传入请求的能力。测试这些设置的更改时,请密切注意RAM使用情况以及可用的文件句柄。由于salt-api是Salt的Python API的简单包装,因此在测试时也请注意Salt的性能。

Future Plans - 未来的计划

既然Salt已经在内部使用Tornado并发库,我们计划通过利用现有流程和事件侦听器来提高API的性能,并使用轻量级协程来促进更多同时HTTP连接和更好地支持同步操作。可以在 issue 26505 中跟踪该工作,但是在该问题解决之前,rest_cherrypy将仍然是官方推荐的REST API

Deployment

部署方式的说明

rest_cherrypy netapi模块是标准的Python WSGI应用程序。 可以采用以下两种方法之一进行部署。

使用CherryPy服务器的salt-api

默认配置是在Salt master节点上面使用salt-api运行此模块以启动基于Python的CherryPy服务器。 该服务器是轻量级的、多线程的、使用SSL加密的,应该被认为可以投入生产。 有关性能预期,请参见以上部分。

使用符合WSGI的Web服务器

该模块可以部署在任何与WSGI兼容的服务器上,例如具有mod_wsgi的Apache或具有FastCGI的Nginx,仅举两个(有很多)。

注意,外部WSGI服务器直接处理URL、路径和SSL证书。 rest_cherrypy配置选项将被忽略,并且salt-api守护程序根本不需要运行。 请记住,除非强制执行SSL,否则Salt身份验证凭据将以明文形式发送

Apache虚拟主机的配置示例:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias *.example.com

    ServerAdmin webmaster@example.com

    LogLevel warn
    ErrorLog /var/www/example.com/logs/error.log
    CustomLog /var/www/example.com/logs/access.log combined

    DocumentRoot /var/www/example.com/htdocs

    WSGIScriptAlias / /path/to/salt/netapi/rest_cherrypy/wsgi.py
</VirtualHost>

REST URI Reference

Salt CherryPy REST URI接口参考资料

/

class salt.netapi.rest_cherrypy.app.LowDataAdapter

这是Salt的REST API接口的主要入口端点。

  1. GET()

下面是关于该API的使用说明。

GET /

  • Request Headers
    • Accept – 期望的响应数据格式
  • Status Codes
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available

request请求的使用示例:

curl -i localhost:8000

      GET / HTTP/1.1
      Host: localhost:8000
      Accept: application/json

response响应:

      Content-Type: application/json
  1. POST(**kwargs)

/login

class salt.netapi.rest_cherrypy.app.Login(*args, **kwargs)

登录并获取一个会话令牌。参数使用方法请参考 Authentication information

  1. GET()

显示登录接口令牌。

GET /login

有关如何登录的说明。

  • Status Codes
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available

request请求的使用示例:

      curl -i localhost:8000/login

      GET /login HTTP/1.1
      Host: localhost:8000
      Accept: text/html

response响应:

        HTTP/1.1 200 OK
        Content-Type: text/html
  1. POST(**kwargs)

针基于Salt的eauth系统进行身份验证

POST /login

  • Request Headers - 请求头
    • X-Auth-Token – 从Login步骤中得到的会话令牌
    • Accept – 期望的响应数据格式
    • Content-Type – 请求正文中使用的数据格式
  • Form Parameters - 表单参数
    • eauth – the eauth backend configured for the user
    • username – username
    • password – password
  • Status Codes - 状态码
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available

request请求的使用示例:

        curl -si localhost:8000/login \
            -c ~/cookies.txt \
            -H "Accept: application/json" \
            -H "Content-type: application/json" \
            -d '{
                "username": "saltuser",
                "password": "saltuser",
                "eauth": "auto"
            }'

        POST / HTTP/1.1
        Host: localhost:8000
        Content-Length: 42
        Content-Type: application/json
        Accept: application/json

        {"username": "saltuser", "password": "saltuser", "eauth": "auto"}

response响应:

        HTTP/1.1 200 OK
        Content-Type: application/json
        Content-Length: 206
        X-Auth-Token: 6d1b722e
        Set-Cookie: session_id=6d1b722e; expires=Sat, 17 Nov 2012 03:23:52 GMT; Path=/

        {"return": {
            "token": "6d1b722e",
            "start": 1363805943.776223,
            "expire": 1363849143.776224,
            "user": "saltuser",
            "eauth": "pam",
            "perms": [
                "grains.*",
                "status.*",
                "sys.*",
                "test.*"
            ]
        }}

/logout

class salt.netapi.rest_cherrypy.app.Logout

清除或使会话令牌失效的工具类。

  1. POST()

销毁当前活动的会话并使会话cookie过期

/minions

class salt.netapi.rest_cherrypy.app.Minions

可以用于对minions进行配置管理的URLs。

  1. GET(mid=None)

可用于获取minions列表或获取minion详细信息的便捷URL。

GET /minions/(mid)

  • Request Headers
    • X-Auth-Token – a session token from Login.
    • Accept – the desired response format.
  • Status Codes
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available

request请求的使用示例:

      curl -i localhost:8000/minions/ms-3

      GET /minions/ms-3 HTTP/1.1
      Host: localhost:8000
      Accept: application/x-yaml

response响应:

       HTTP/1.1 200 OK
       Content-Length: 129005
       Content-Type: application/x-yaml

       return:
       - ms-3:
           grains.items:
               ...
  1. POST(**kwargs)

启动一个执行命令并立即返回job id 。

POST /minions

  • Request Headers
    • X-Auth-Token – a session token from Login.
    • Accept – the desired response format.
    • Content-Type – the format of the request body.
  • Response Headers
    • Content-Type – the format of the response body; depends on the Accept request header.
  • Status Codes
    • 200 – success

    • 400 – bad or malformed request

    • 401 – authentication required

    • 406 – requested Content-Type not available

      描述Salt命令内容的lowstate数据必须在请求正文中发送。 client选项将被设置为local_async()

request请求的使用示例:

      curl -sSi localhost:8000/minions \
          -b ~/cookies.txt \
          -H "Accept: application/x-yaml" \
          -d '[{"tgt": "*", "fun": "status.diskusage"}]'

      POST /minions HTTP/1.1
      Host: localhost:8000
      Accept: application/x-yaml
      Content-Type: application/json

      tgt=*&fun=status.diskusage

response响应:

       HTTP/1.1 202 Accepted
       Content-Length: 86
       Content-Type: application/x-yaml

       return:
       - jid: '20130603122505459265'
         minions: [ms-4, ms-3, ms-2, ms-1, ms-0]
       _links:
         jobs:
           - href: /jobs/20130603122505459265

/jobs

class salt.netapi.rest_cherrypy.app.Jobs

  1. GET(jid=None, timeout=’’)

一个方便使用的URL,用于获取先前运行的作业的列表或从单个作业中获取返回数据。

GET /jobs/(jid)

列出作业列表或显示作业缓存中的单个作业的详细信息。

  • Request Headers
    • X-Auth-Token – a session token from Login.
    • Accept – the desired response format.
  • Status Codes
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available

request请求的使用示例:

        curl -i localhost:8000/jobs

        GET /jobs HTTP/1.1
        Host: localhost:8000
        Accept: application/x-yaml

response响应:

        HTTP/1.1 200 OK
        Content-Length: 165
        Content-Type: application/x-yaml

        return:
        - '20121130104633606931':
            Arguments:
            - '3'
            Function: test.fib
            Start Time: 2012, Nov 30 10:46:33.606931
            Target: jerry
            Target-type: glob

request请求的使用示例:

        curl -i localhost:8000/jobs/20121130104633606931

        GET /jobs/20121130104633606931 HTTP/1.1
        Host: localhost:8000
        Accept: application/x-yaml

response响应:

        HTTP/1.1 200 OK
        Content-Length: 73
        Content-Type: application/x-yaml

        info:
        - Arguments:
            - '3'
            Function: test.fib
            Minions:
            - jerry
            Start Time: 2012, Nov 30 10:46:33.606931
            Target: '*'
            Target-type: glob
            User: saltdev
            jid: '20121130104633606931'
        return:
        - jerry:
            - - 0
            - 1
            - 1
            - 2
            - 6.9141387939453125e-06

/run

class salt.netapi.rest_cherrypy.app.Run

绕过常规的session处理,运行管理命令。

salt-api不执行授权,是由Salt的eauth系统执行授权。 Local/Runner/WheelClient都可以接受username/password/eauth 或者 token kwargs ,然后交由eauth系统执行检查。 rest_cherrypy中的会话机制仅将会话与Salt eauth令牌配对,然后自动将Token kwarg传入。

如果您已经有一个Salt eauth token了(可能是由Auth Runner模块中的mk_token函数生成的),则没有理由再使用sessions。

该URL端点接受用使用username, password, eauth这三个参数,或者是一个 token kwarg关键字参数,并且根本不使用sessions。

  1. POST(**kwargs)

绕过常规的session处理,运行管理命令。除此之外,该URL端点与root URL (/)相同。

POST /run

描述Salt命令的lowstate数据数组必须在请求正文中发送。

  • Status Codes
    • 200 – success
    • 400 – bad or malformed request
    • 401 – authentication required
    • 406 – requested Content-Type not available

request请求的使用示例:

        curl -sS localhost:8000/run \
            -H 'Accept: application/x-yaml' \
            -H 'Content-type: application/json' \
            -d '[{
                "client": "local",
                "tgt": "*",
                "fun": "test.ping",
                "username": "saltdev",
                "password": "saltdev",
                "eauth": "auto"
            }]'

或者是使用 Salt Eauth token:

        curl -sS localhost:8000/run \
            -H 'Accept: application/x-yaml' \
            -H 'Content-type: application/json' \
            -d '[{
                "client": "local",
                "tgt": "*",
                "fun": "test.ping",
                "token": "<salt eauth token here>"
            }]'

        POST /run HTTP/1.1
        Host: localhost:8000
        Accept: application/x-yaml
        Content-Length: 75
        Content-Type: application/json

        [{"client": "local", "tgt": "*", "fun": "test.ping", "username": "saltdev", "password": "saltdev", "eauth": "auto"}]

response响应:

        HTTP/1.1 200 OK
        Content-Length: 73
        Content-Type: application/x-yaml

        return:
        - ms-0: true
          ms-1: true
          ms-2: true
          ms-3: true
          ms-4: true

/run enpoint也可以用于使用salt-ssh子系统执行命令。

使用salt-ssh时,不应提供eauth认证凭据。 相反地,身份验证应由SSH层本身处理。 使用salt-ssh客户端时也不需要运行Salt Master。 相反,Salt配置目录中只能存在一个roster名册文件。

所有SSH客户端请求都是同步执行的。

SSH客户端请求的示例:

        curl -sS localhost:8000/run \
            -H 'Accept: application/x-yaml' \
            -d client='ssh' \
            -d tgt='*' \
            -d fun='test.ping'

        POST /run HTTP/1.1
        Host: localhost:8000
        Accept: application/x-yaml
        Content-Length: 75
        Content-Type: application/x-www-form-urlencoded

        client=ssh&tgt=*&fun=test.ping
SSH response响应:
        return:
        - silver:
          fun: test.ping
          fun_args: []
          id: silver
          jid: '20141203103525666185'
          retcode: 0
          return: true
          success: true

/events

class salt.netapi.rest_cherrypy.app.Events

对外暴露Salt的事件总线。

Salt master主机上的事件总线对外暴露了各种各样的东西,特别是在master主机上开始执行时,以及在minions最终返回其结果时。 该URL提供了运行中的Salt基础结构的一个实时信息窗口。

See also: Events & Reactor

  1. GET(token=None, salt_token=None)

Salt master事件总线的一个HTTP流。

该流按照服务器发送事件(SSE)规范进行格式化。 每个事件的格式均为JSON。

GET /events

  • Status Codes
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available
  • Query Parameters
    • token – 可选参数,包含通常通过X-Auth-Token header提供的token,以便允许在EventSource API中不包含CORS支持的浏览器中进行跨域请求。 例如。, curl -NsS localhost:8000/events?token=308650d
    • salt_token – 可选参数,包含原始Salt eauth令牌(不要与/login URL返回的令牌混淆)。 例如, curl -NsS localhost:8000/events?salt_token=30742765

request请求示例:

        curl -NsS localhost:8000/events

        GET /events HTTP/1.1
        Host: localhost:8000

response响应:

注意,tag字段不是规范的一部分。 符合SSE的客户端应忽略未知字段。 此添加使不兼容的客户端仅监视某些标签,而不必每次都反序列化JSON对象。

        HTTP/1.1 200 OK
        Connection: keep-alive
        Cache-Control: no-cache
        Content-Type: text/event-stream;charset=utf-8

        retry: 400

        tag: salt/job/20130802115730568475/new
        data: {'tag': 'salt/job/20130802115730568475/new', 'data': {'minions': ['ms-4', 'ms-3', 'ms-2', 'ms-1', 'ms-0']}}

        tag: salt/job/20130802115730568475/ret/jerry
        data: {'tag': 'salt/job/20130802115730568475/ret/jerry', 'data': {'jid': '20130802115730568475', 'return': True, 'retcode': 0, 'success': True, 'cmd': '_return', 'fun': 'test.ping', 'id': 'ms-1'}}

这个事件流可以容易得使用JavaScript解析处理:

        var source = new EventSource('/events');
        source.onopen = function() { console.info('Listening ...') };
        source.onerror = function(err) { console.error(err) };
        source.onmessage = function(message) {
            var saltEvent = JSON.parse(message.data);
            console.log(saltEvent.tag, saltEvent.data);
        };

请注意,SSE流是快速且完全异步的,而Salt是非常快的。如果使用常规POST请求创建了作业,则在POST请求的响应到达之前,作业返回将在SSE流上可用。在设计应用程序时,必须考虑到异步性。以下是一些一般准则。
- 在创建任何事件前就订阅SSE流。
- 在SSE事件到达时直接对其进行处理,而无需等待任何其他过程首先“完成”(例如ajax请求)。
- 如果必须将事件流用于同步查找,请保留事件的缓冲区。
- 将Salt的事件流直接写到DOM时要谨慎。它非常忙,可以迅速使分配给浏览器选项卡的内存不堪重负。

该文件旁边提供了一个完整的有效概念验证目的的JavaScript应用程序。可以通过将浏览器指向正在运行的rest_cherrypy实例中的/app端点来查看它。

或使用CORS:

        var source = new EventSource('/events?token=ecd589e4e01912cf3c4035afad73426dbb8dba75', {withCredentials: true});

也可以通过shell消费流。

记录由空白行分隔; 在尝试反序列化JSON之前,需要手动删除data:tag:前缀。

curl的 -N 标识关闭了输入缓存功能,因为我们需要能增量的处理流。

这是打印每个事件的一个基本示例:

        curl -NsS localhost:8000/events |\
                while IFS= read -r line ; do
                    echo $line
                done

下面是使用 awk 基于 tag 过滤事件的例子:

        curl -NsS localhost:8000/events |\
                awk '
                    BEGIN { RS=""; FS="\\n" }
                    $1 ~ /^tag: salt\/job\/[0-9]+\/new$/ { print $0 }
                '
        tag: salt/job/20140112010149808995/new
        data: {"tag": "salt/job/20140112010149808995/new", "data": {"tgt_type": "glob", "jid": "20140112010149808995", "tgt": "jerry", "_stamp": "2014-01-12_01:01:49.809617", "user": "shouse", "arg": [], "fun": "test.ping", "minions": ["jerry"]}}
        tag: 20140112010149808995
        data: {"tag": "20140112010149808995", "data": {"fun_args": [], "jid": "20140112010149808995", "return": true, "retcode": 0, "success": true, "cmd": "_return", "_stamp": "2014-01-12_01:01:49.819316", "fun": "test.ping", "id": "jerry"}}

/hook

class salt.netapi.rest_cherrypy.app.Webhook

一个通用的Web hook入口点,可在Salt的事件总线上触发事件。

外部服务可以将数据发布到此URL,以触发Salt中的相应事件。例如,Amazon SNS、Jenkins-CI或Travis-CI或GitHub Web hooks。

注意安全性

Salt的Reactor可以运行任何代码。响应钩子事件的Reactor SLS负责验证该事件来自受信任的源并包含有效数据。

这是一个通用接口,如何确保安全由您决定!

此URL需要身份验证,但是并非所有外部服务都可以配置为进行身份验证。因此,可以有选择地禁用此URL的身份验证。建议遵循最佳做法-始终使用SSL、传递密钥、将防火墙配置为仅允许来自已知来源的流量等。

事件数据取自请求的正文。Content-Type header适用于有效负载。

事件标记的前缀是`salt/netapi/hook`,URL路径附加在末尾。例如,发送到`/hook/mycompany/myapp/mydata`的`POST`请求将产生一个带有`Salt/netapi/hook/mycompany/myapp/mydata`标签的Salt事件。

以下是一个示例`.travis.yml`文件,用于将成功运行测试的通知发送给Salt:
    language: python
    script: python -m unittest tests
    after_success:
        - |
            curl -sSk https://saltapi-url.example.com:8000/hook/travis/build/success                         -d branch="${TRAVIS_BRANCH}"                         -d commit="${TRAVIS_COMMIT}"

See also:Events & Reactor, reactor

  1. POST(*args, **kwargs)

使用自定义的标签和数据,在Salt中触发一个事件。

POST /hook

  • Status Codes
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available
    • 413 – request body is too large

request请求使用示例:

        curl -sS localhost:8000/hook \
            -H 'Content-type: application/json' \
            -d '{"foo": "Foo!", "bar": "Bar!"}'

        POST /hook HTTP/1.1
        Host: localhost:8000
        Content-Length: 16
        Content-Type: application/json

        {"foo": "Foo!", "bar": "Bar!"}

response响应示例:

        HTTP/1.1 200 OK
        Content-Length: 14
        Content-Type: application/json

        {"success": true}

作为一个实际可以运行的示例,内部的持续集成构建服务器可以将HTTP POST请求发送到URL https://localhost:8000/hook/mycompany/build/success,其中包含构建结果和该版本的SHA被构建为JSON。 然后,这将在Salt中产生以下事件,该事件可用于通过Salt的Reactor继续启动下一个步骤的应用部署:

        Event fired at Fri Feb 14 17:40:11 2014
        *************************
        Tag: salt/netapi/hook/mycompany/build/success
        Data:
        {'_stamp': '2014-02-14_17:40:11.440996',
            'headers': {
                'X-My-Secret-Key': 'F0fAgoQjIT@W',
                'Content-Length': '37',
                'Content-Type': 'application/json',
                'Host': 'localhost:8000',
                'Remote-Addr': '127.0.0.1'},
            'post': {'revision': 'aa22a3c4b2e7', 'result': True}}

Salt 的 Reactor 响应器将会监控这类事件:

        reactor:
          - 'salt/netapi/hook/mycompany/build/*':
            - /srv/reactor/react_ci_builds.sls

并最终完成应用程序的部署工作:

        {% set secret_key = data.get('headers', {}).get('X-My-Secret-Key') %}
        {% set build = data.get('post', {}) %}

        {% if secret_key == 'F0fAgoQjIT@W' and build.result == True %}
        deploy_my_app:
          cmd.state.sls:
            - tgt: 'application*'
            - arg:
              - myapp.deploy
            - kwarg:
                pillar:
                  revision: {{ revision }}
        {% endif %}

/keys

class salt.netapi.rest_cherrypy.app.Keys

用于管理minion keys的便捷URLs。

New in version 2014.7.0.

这些URL包含了 key wheel module 功能提供的功能。

  1. GET(mid=None)

显示minion keys列表或特定key的详细信息。

*New in version 2014.7.0.*

GET /keys/(mid)

  • Request Headers
    • X-Auth-Token – a session token from Login.
    • Accept – the desired response format.
  • Status Codes
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available

request请求使用示例:

      curl -i localhost:8000/keys

      GET /keys HTTP/1.1
      Host: localhost:8000
      Accept: application/x-yaml

response响应示例:

      HTTP/1.1 200 OK
      Content-Length: 165
      Content-Type: application/x-yaml

      return:
        local:
        - master.pem
        - master.pub
        minions:
        - jerry
        minions_pre: []
        minions_rejected: []

request请求使用示例:

      curl -i localhost:8000/keys/jerry

      GET /keys/jerry HTTP/1.1
      Host: localhost:8000
      Accept: application/x-yaml

response响应示例:

      HTTP/1.1 200 OK
      Content-Length: 73
      Content-Type: application/x-yaml

      return:
        minions:
          jerry: 51:93:b3:d0:9f:3a:6d:e5:28:67:c2:4b:27:d6:cd:2b
  1. POST(**kwargs)

可以方便的为minion生成密钥并自动接受新密钥。

接受与key.gen_accept相同的所有参数。

注意:关于curl的使用请避免-i标志,否则将会也写入HTTP header数据,以致于生成无效的tar文件。

下面是在kickstart脚本中用来引导和配置新的minion的示例:

      %post
      mkdir -p /etc/salt/pki/minion
      curl -sSk https://localhost:8000/keys \
              -d mid=jerry \
              -d username=kickstart \
              -d password=kickstart \
              -d eauth=pam \
          | tar -C /etc/salt/pki/minion -xf -

      mkdir -p /etc/salt/minion.d
      printf 'master: 10.0.0.5\nid: jerry' > /etc/salt/minion.d/id.conf
      %end

POST /keys

生成公钥和私钥,并打包为一个tar压缩包文件返回。

身份验证凭据必须在请求中传递。

  • Status Codes
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available

request请求使用示例:

      curl -sSk https://localhost:8000/keys \
              -d mid=jerry \
              -d username=kickstart \
              -d password=kickstart \
              -d eauth=pam \
              -o jerry-salt-keys.tar

      POST /keys HTTP/1.1
      Host: localhost:8000

response响应示例:

      HTTP/1.1 200 OK
      Content-Length: 10240
      Content-Disposition: attachment; filename="saltkeys-jerry.tar"
      Content-Type: application/x-tar

      jerry.pub0000644000000000000000000000070300000000000010730 0ustar  00000000000000

/ws

class salt.netapi.rest_cherrypy.app.WebsocketEndpoint

打开一个与Salt的事件总线的WebSocket连接。

Salt master主机上的事件总线公开了各种各样的东西,特别是在master主机上开始执行时,以及在minions最终返回其结果时。 该URL提供了运行中的Salt基础结构的实时令牌窗口。 使用websocket作为传输机制。

See also:Events & Reactor

  1. GET(token=None, **kwargs)

返回一个与Salt的事件总线的WebSocket连接。

GET /ws/(token)

  • Query format_events

    如果请求中包含format_events 的URL参数,则事件流将进行服务器端进行内容格式化。 这对于需要避免在客户端进行格式化时很有用: curl -NsS <...snip...> localhost:8000/ws?format_events

  • Reqheader X-Auth-Token
    一个在Login步骤中获取的身份认证token。

  • Status 101
    切换至websockets协议。

  • Status 401
    需要通过身份验证。

  • Status 406
    request请求中的Content-Type无效。

request请求的使用示例:

      curl -NsSk \
          -H 'X-Auth-Token: ffedf49d' \
          -H 'Host: localhost:8000' \
          -H 'Connection: Upgrade' \
          -H 'Upgrade: websocket' \
          -H 'Origin: https://localhost:8000' \
          -H 'Sec-WebSocket-Version: 13' \
          -H 'Sec-WebSocket-Key: '"$(echo -n $RANDOM | base64)" \
          localhost:8000/ws

      GET /ws HTTP/1.1
      Connection: Upgrade
      Upgrade: websocket
      Host: localhost:8000
      Origin: https://localhost:8000
      Sec-WebSocket-Version: 13
      Sec-WebSocket-Key: s65VsgHigh7v/Jcf4nXHnA==
      X-Auth-Token: ffedf49d

response响应的示例:

      HTTP/1.1 101 Switching Protocols
      Upgrade: websocket
      Connection: Upgrade
      Sec-WebSocket-Accept: mWZjBV9FCglzn1rIKJAxrTFlnJE=
      Sec-WebSocket-Version: 13

对于无法配置为发送的请求携带身份验证header或cookie的浏览器客户端,可以选择性地将身份验证令牌作为URL的一部分传递: curl -NsS <...snip...> localhost:8000/ws/ffedf49d

可以很容易地使用JavaScript解析处理事件流数据:

      // Note, you must be authenticated!
      var source = new Websocket('ws://localhost:8000/ws/d0ce6c1a');
      source.onerror = function(e) { console.debug('error!', e); };
      source.onmessage = function(e) { console.debug(e.data); };

      source.send('websocket client ready')

      source.close();

或者使用Python。例如,使用 Python 模块 websocket-client

      # Note, you must be authenticated!

      from websocket import create_connection

      ws = create_connection('ws://localhost:8000/ws/d0ce6c1a')
      ws.send('websocket client ready')

      # Look at https://pypi.python.org/pypi/websocket-client/ for more
      # examples.
      while listening_to_events:
          print ws.recv()

      ws.close()

上面的示例显示了如何建立与Salt的websocket连接以及如何通过向websocket客户端发送信号通知激活Salt的事件流的实时更新。

/stats

class salt.netapi.rest_cherrypy.app.Stats

对外暴露 CherryPy server 的运行统计数据。

  1. GET()

返回从CherryPy服务器收集的统计信息的转储。

GET /stats

  • Request Headers
    • X-Auth-Token – a session token from Login.
    • Accept – the desired response format.
  • Response Headers
    • Content-Type – the format of the response body; depends on the Accept request header.
  • Status Codes
    • 200 – success
    • 401 – authentication required
    • 406 – requested Content-Type not available
 类似资料: