SALT-API(7)

NAME
salt-api - salt-api Documentation

salt-api is a modular interface on top of Salt that can provide a variety of entry points into a running Salt system. It can start and manage multiple interfaces allowing a REST API to coexist with XMLRPC or even a Websocket API.

GETTING STARTED

1.  Install salt-api on the same machine as your Salt master.

2.  Edit your Salt master config file for all required options for each netapi module you wish to run.

3.  Install any required additional libraries or software for each netapi module you wish to run.

4.  Run salt-api which will then start all configured netapi modules.

    NOTE: Each netapi module will have differing configuration requirements and differing required software libraries.

    Exactly like the various module types in Salt (execution modules, renderer modules, returner modules, etc.), netapi modules in salt-api will not be loaded into memory or started if all requirements are not met.

INSTALLATION QUICKSTART

  salt-api Quickstart

salt-api manages netapi modules which are modules that (usually) bind to a port and start a service. Each netapi module will have specific requirements for third-party libraries and configuration (which goes in the master config file). Read the documentation for each netapi module to determine what is needed.

For example, the rest_cherrypy netapi module requires that CherryPy be installed and that a rest_cherrypy section be added to the master config that specifies which port to listen on.

  Installation

  PyPI

https://pypi.python.org/pypi/salt-api

pip install salt-api

  RHEL, Fedora, CentOS

RPMs are available in the Fedora repositories and EPEL:

yum install salt-api

  Ubuntu

PPA packages available for Ubuntu on LaunchPad:

sudo add-apt-repository ppa:saltstack/salt
sudo apt-get update
sudo apt-get install salt-api

  openSUSE, SLES

RPMs are available via the OBS:

zypper install salt-api

NETAPI MODULES

The core functionality for salt-api lies in pluggable netapi modules that adhere to the simple interface of binding to a port and starting a service. salt-api can manage one or many services concurrently.

  Full list of netapi modules

  Full list of netapi modules

  rest_cherrypy

  A REST API for Salt

depends

•   CherryPy Python module

configuration
    All authentication is done through Salt's external auth system. Be sure that it is enabled and the user you are authenticating as has permissions for all the functions you will be running.

    Example production configuration block; add to the Salt master config file:

    rest_cherrypy:
      port: 8000
      ssl_crt: /etc/pki/tls/certs/localhost.crt
      ssl_key: /etc/pki/tls/certs/localhost.key

    The REST interface strongly recommends a secure HTTPS connection since Salt authentication credentials will be sent over the wire. If you don't already have a certificate and don't wish to buy one, you can generate a self-signed certificate using the create_self_signed_cert() function in Salt (note the dependencies for this module):

    % salt-call tls.create_self_signed_cert

    All available configuration options are detailed below. These settings configure the CherryPy HTTP server and do not apply when using an external server such as Apache or Nginx.

port
    Required

    The port for the webserver to listen on.

host
    0.0.0.0 The socket interface for the HTTP server to listen on.

    New in version 0.8.2.

debug
    False Starts the web server in development mode. It will reload itself when the underlying code is changed and will output more debugging info.

ssl_crt
    The path to a SSL certificate. (See below)

ssl_key
    The path to the private key for your SSL certificate. (See below)

disable_ssl
    A flag to disable SSL. Warning: your Salt authentication credentials will be sent in the clear!

    New in version 0.8.3.

thread_pool
    100 The number of worker threads to start up in the pool.

    Changed in version 0.8.4: Previous versions defaulted to a pool of 10

socket_queue_size
    30 Specify the maximum number of HTTP connections to queue.

    Changed in version 0.8.4: Previous versions defaulted to 5 connections.

max_request_body_size
    1048576 Changed in version 0.8.4: Previous versions defaulted to 104857600 for the size of the request body

collect_stats
    False Collect and report statistics about the CherryPy server

    New in version 0.8.4.

    Reports are available via the Stats URL.

static
    A filesystem path to static HTML/JavaScript/CSS/image assets.

static_path
    /static The URL prefix to use when serving static assets out of the directory specified in the static setting.

    New in version 0.8.2.

app A filesystem path to an HTML file that will be served as a static file. This is useful for bootstrapping a single-page JavaScript app.

    New in version 0.8.2.

app_path
    /app The URL prefix to use for serving the HTML file specified in the app setting. This should be a simple name containing no slashes.

    Any path information after the specified path is ignored; this is useful for apps that utilize the HTML5 history API.

    New in version 0.8.2.

root_prefix
    / A URL path to the main entry point for the application. This is useful for serving multiple applications from the same URL.

    New in version 0.8.4.

  Authentication

Authentication is performed by passing a session token with each request. The token may be sent either via a custom header named X-Auth-Token or sent inside a cookie. (The result is the same but browsers and some HTTP clients handle cookies automatically and transparently so it is a convenience.)

Token are generated via the Login URL.

SEE ALSO: You can bypass the session handling via the Run URL.

  Usage

You access a running Salt master via this module by sending HTTP requests to the URLs detailed below.

Content negotiation

    This REST interface is flexible in what data formats it will accept as well as what formats it will return (e.g., JSON, YAML, x-www-form-urlencoded).

•   Specify the format of data you are sending in a request by including the Content-Type header.

•   Specify your desired output format for the response with the Accept header.

    This REST interface expects data sent in POST and PUT requests to be in the format of a list of lowstate dictionaries. This allows you to specify multiple commands in a single request.

lowstate
    A dictionary containing various keys that instruct Salt which command to run, where that command lives, any parameters for that command, any authentication credentials, what returner to use, etc.

    Salt uses the lowstate data format internally in many places to pass command data between functions. Salt also uses lowstate for the LocalClient() Python API interface.

    For example (in JSON format):

    [{
        'client': 'local',
        'tgt': '*',
        'fun': 'test.fib',
        'arg': ['10'],
    }]

x-www-form-urlencoded

    This REST interface accepts data in the x-www-form-urlencoded format. This is the format used by HTML forms, the default format used by curl, the default format used by many JavaScript AJAX libraries (such as jQuery), etc. This format will be converted to the lowstate format as best as possible with the caveats below. It is always preferable to format data in the lowstate format directly in a more capable format such as JSON or YAML.

•   Only a single command may be sent in this format per HTTP request.

•   Multiple arg params will be sent as a single list of params.

    Note, some popular frameworks and languages (notably jQuery, PHP, and Ruby on Rails) will automatically append empty brackets onto repeated parameters. E.g., arg=one, arg=two will be sent as arg[]=one, arg[]=two. Again, it is preferable to send lowstate via JSON or YAML directly by specifying the Content-Type header in the request.

  URL reference

The main entry point is the root URL (/) and all functionality is available at that URL. The other URLs are largely convenience URLs that wrap that main entry point with shorthand or specialized functionality.

  Deployment

The rest_cherrypy netapi module is a standard Python WSGI app. It can be deployed one of two ways.

  salt-api using the CherryPy server

The default configuration is to run this module using salt-api to start the Python-based CherryPy server. This server is lightweight, multi-threaded, encrypted with SSL, and should be considered production-ready.

  Using a WSGI-compliant web server

This module may be deplayed on any WSGI-compliant server such as Apache with mod_wsgi or Nginx with FastCGI, to name just two (there are many).

Note, external WSGI servers handle URLs, paths, and SSL certs directly. The rest_cherrypy configuration options are ignored and the salt-api daemon does not need to be running at all. Remember Salt authentication credentials are sent in the clear unless SSL is being enforced!

An example Apache virtual host configuration:

<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/saltapi/netapi/rest_cherrypy/wsgi.py
</VirtualHost>

  REST URI Reference

class saltapi.netapi.rest_cherrypy.app.LowDataAdapter
    The primary entry point to the REST API. All functionality is available through this URL. The other available URLs provide convenience wrappers around this URL.

GET()

GET /
    An explanation of the API with links of where to go next.

    Example request:

    % curl -i localhost:8000

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

    Example response:

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

Status 200
    success

Status 401
    authentication required

Status 406
    requested Content-Type not available

class saltapi.netapi.rest_cherrypy.app.Login(*args, **kwargs)
    All interactions with this REST API must be authenticated. Authentication is performed through Salt's eauth system. You must set the eauth backend and allowed users by editing the external_auth section in your master config.

    Authentication credentials are passed to the REST API via a session id in one of two ways:

    If the request is initiated from a browser it must pass a session id via a cookie and that session must be valid and active.

    If the request is initiated programmatically, the request must contain a X-Auth-Token header with valid and active session id.

GET()
    Present the login interface

GET /login
    An explanation of how to log in.

    Example request:

    % curl -i localhost:8000/login

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

    Example response:

    HTTP/1.1 200 OK
    Content-Type: text/html

Status 401
    authentication required

Status 406
    requested Content-Type not available

POST(**kwargs)
    Authenticate against Salt's eauth system

    Changed in version 0.8.0: No longer returns a 302 redirect on success.

    Changed in version 0.8.1: Returns 401 on authentication failure

POST /login
    Example request:

    % curl -si localhost:8000/login \
            -H "Accept: application/json" \
            -d username='saltuser' \
            -d password='saltpass' \
            -d eauth='pam'

    POST / HTTP/1.1
    Host: localhost:8000
    Content-Length: 42
    Content-Type: application/x-www-form-urlencoded
    Accept: application/json
    username=saltuser&password=saltpass&eauth=pam

    Example 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.*"
        ]
    }}

Form eauth
    the eauth backend configured in your master config

Form username
    username

Form password
    password

Status 200
    success

Status 401
    could not authenticate using provided credentials

Status 406
    requested Content-Type not available

class saltapi.netapi.rest_cherrypy.app.Logout

POST()
    Destroy the currently active session and expire the session cookie

    New in version 0.8.0.

class saltapi.netapi.rest_cherrypy.app.Minions

GET(mid=None)
    A convenience URL for getting lists of minions or getting minion details

GET /minions/(mid)
    Get grains, modules, functions, and inline function documentation for all minions or a single minion

    Example request:

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

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

    Example response:

    HTTP/1.1 200 OK
    Content-Length: 129005
    Content-Type: application/x-yaml
    return:
    - ms-3:
        grains.items:
          ...

Parameters
    mid -- (optional) a minion id

Status 200
    success

Status 401
    authentication required

Status 406
    requested Content-Type not available

POST(**kwargs)
    Start an execution command and immediately return the job id

POST /minions
    You must pass low-data in the request body either from an HTML form or as JSON or YAML. The client option is pre-set to local_async.

    Example request:

    % curl -sSi localhost:8000/minions \
        -H "Accept: application/x-yaml" \
        -d tgt='*' \
        -d fun='status.diskusage'

    POST /minions HTTP/1.1
    Host: localhost:8000
    Accept: application/x-yaml
    Content-Length: 26
    Content-Type: application/x-www-form-urlencoded
    tgt=*&fun=status.diskusage

    Example 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

Form lowstate
    lowstate data for the LocalClient; the client parameter will be set to local_async

    Lowstate may be supplied in any supported format by specifying the Content-Type header in the request. Supported formats are listed in the Alternates response header.

Status 202
    success

Status 401
    authentication required

Status 406
    requested Content-Type not available

class saltapi.netapi.rest_cherrypy.app.Jobs

GET(jid=None)
    A convenience URL for getting lists of previously run jobs or getting the return from a single job

GET /jobs/(jid)
    Get grains, modules, functions, and inline function documentation for all minions or a single minion

    Example request:

    % curl -i localhost:8000/jobs

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

    Example 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

    Example request:

    % curl -i localhost:8000/jobs/20121130104633606931

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

    Example 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

Parameters
    mid -- (optional) a minion id

Status 200
    success

Status 401
    authentication required

Status 406
    requested Content-Type not available

class saltapi.netapi.rest_cherrypy.app.Run

POST(**kwargs)
    Run commands bypassing the normal session handling

    New in version 0.8.0.

POST /run
    This entry point is primarily for "one-off" commands. Each request must pass full Salt authentication credentials. Otherwise this URL is identical to the root (/) execution URL.

    Example request:

    % curl -sS localhost:8000/run \
        -H 'Accept: application/x-yaml' \
        -d client='local' \
        -d tgt='*' \
        -d fun='test.ping' \
        -d username='saltdev' \
        -d password='saltdev' \
        -d eauth='pam'

    POST /run HTTP/1.1
    Host: localhost:8000
    Accept: application/x-yaml
    Content-Length: 75
    Content-Type: application/x-www-form-urlencoded
    client=local&tgt=*&fun=test.ping&username=saltdev&password=saltdev&eauth=pam

    Example 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

Form lowstate
    A list of lowstate data appropriate for the client specified client interface. Full external authentication credentials must be included.

Status 200
    success

Status 401
    authentication failed

Status 406
    requested Content-Type not available

class saltapi.netapi.rest_cherrypy.app.Events
    The event bus on the Salt master exposes a large variety of things, notably when executions are started on the master and also when minions ultimately return their results. This URL provides a real-time window into a running Salt infrastructure.

GET(token=None)
    Return an HTTP stream of the Salt master event bus; this stream is formatted per the Server Sent Events (SSE) spec

    New in version 0.8.3.

    Browser clients currently lack Cross-origin resource sharing (CORS) support for the EventSource() API. Cross-domain requests from a browser may instead pass the X-Auth-Token value as an URL parameter:

    % curl -NsS localhost:8000/events/6d1b722e

GET /events
    Example request:

    % curl -NsS localhost:8000/events

    GET /events HTTP/1.1
    Host: localhost:8000

    Example response:

    HTTP/1.1 200 OK
    Connection: keep-alive
    Cache-Control: no-cache
    Content-Type: text/event-stream;charset=utf-8
    retry: 400
    data: {'tag': '', 'data': {'minions': ['ms-4', 'ms-3', 'ms-2', 'ms-1', 'ms-0']}}
    data: {'tag': '20130802115730568475', 'data': {'jid': '20130802115730568475', 'return': True, 'retcode': 0, 'success': True, 'cmd': '_return', 'fun': 'test.ping', 'id': 'ms-1'}}

    The event stream can be easily consumed via JavaScript:

    # Note, you must be authenticated!
    var source = new EventSource('/events');
    source.onopen = function() { console.debug('opening') };
    source.onerror = function(e) { console.debug('error!', e) };
    source.onmessage = function(e) { console.debug(e.data) };

    It is also possible to consume the stream via the shell.

    Records are separated by blank lines; the data: and tag: prefixes will need to be removed manually before attempting to unserialize the JSON.

    curl's -N flag turns off input buffering which is required to process the stream incrementally.

    Here is a basic example of printing each event as it comes in:

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

    Here is an example of using awk to filter events based on 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"}}

Status 200
    success

Status 401
    could not authenticate using provided credentials

class saltapi.netapi.rest_cherrypy.app.Webhook
    A generic web hook entry point that fires an event on Salt's event bus

    External services can POST data to this URL to trigger an event in Salt. For example, Jenkins-CI or Travis-CI, or GitHub web hooks.

    This entry point does not require authentication. The event data is taken from the request body.

    NOTE: Be mindful of security

    Salt's Reactor can run any code. If you write a Reactor SLS that responds to a hook event be sure to validate that the event came from a trusted source and contains valid data! Pass a secret key and use SSL.

    This is a generic interface and securing it is up to you!

    The event tag is prefixed with salt/netapi/hook and the URL path is appended to the end. For example, a POST request sent to /hook/mycompany/myapp/mydata will produce a Salt event with the tag salt/netapi/hook/mycompany/myapp/mydata. See the Salt Reactor documentation for how to react to events with various tags.

    The following is an example .travis.yml file to send notifications to Salt of successful test runs:

    language: python
    script: python -m unittest tests
    after_success:
        - 'curl -sS http://saltapi-url.example.com:8000/hook/travis/build/success -d branch="${TRAVIS_BRANCH}" -d commit="${TRAVIS_COMMIT}"'

POST(*args, **kwargs)
    Fire an event in Salt with a custom event tag and data

    New in version 0.8.4.

POST /hook
    Example request:

    % curl -sS localhost:8000/hook -d foo='Foo!' -d bar='Bar!'

    POST /hook HTTP/1.1
    Host: localhost:8000
    Content-Length: 16
    Content-Type: application/x-www-form-urlencoded
    foo=Foo&bar=Bar!

    Example response:

    HTTP/1.1 200 OK
    Content-Length: 14
    Content-Type: application/json
    {"success": true}

    As a practical example, an internal continuous-integration build server could send an HTTP POST request to the URL http://localhost:8000/hook/mycompany/build/success which contains the result of a build and the SHA of the version that was built as JSON. That would then produce the following event in Salt that could be used to kick off a deployment via Salt's 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's Reactor could listen for the event:

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

    And finally deploy the new build:

    {% 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
          - 'pillar={revision: {{ revision }}}'
    {% endif %}

Status 200
    success

Status 406
    requested Content-Type not available

Status 413
    request body is too large

class saltapi.netapi.rest_cherrypy.app.Stats
    Expose statistics on the running CherryPy server

GET()
    Return a dump of statistics collected from the CherryPy server

Status 200
    success

Status 406
    requested Content-Type not available

  rest_wsgi

  A minimalist REST API for Salt

This rest_wsgi module provides a no-frills REST interface to a running Salt master. There are no dependencies.

Please read this introductory section in entirety before deploying this module.

configuration
    All authentication is done through Salt's external auth system. Be sure that it is enabled and the user you are authenticating as has permissions for all the functions you will be running.

    The configuration options for this module resides in the Salt master config file. All available options are detailed below.

port
    Required

    The port for the webserver to listen on.

    Example configuration:

    rest_wsgi:
      port: 8001

    This API is not very "RESTful"; please note the following:

•   All requests must be sent to the root URL (/).

•   All requests must be sent as a POST request with JSON content in the request body.

•   All responses are in JSON.

    SEE ALSO: rest_cherrypy

    The rest_cherrypy module is more full-featured, production-ready, and has builtin security features.

  Deployment

The rest_wsgi netapi module is a standard Python WSGI app. It can be deployed one of two ways.

  salt-api using a development-only server

If run directly via salt-api it uses the wsgiref.simple_server() that ships in the Python standard library. This is a single-threaded server that is intended for testing and development. This server does not use encryption; please note that raw Salt authentication credentials must be sent with every HTTP request.

Running this module via salt-api is not recommended for most use!

  Using a WSGI-compliant web server

This module may be run via any WSGI-compliant production server such as Apache with mod_wsgi or Nginx with FastCGI.

It is highly recommended that this app be used with a server that supports HTTPS encryption since raw Salt authentication credentials must be sent with every request. Any apps that access Salt through this interface will need to manually manage authentication credentials (either username and password or a Salt token). Tread carefully.

  Usage examples

POST /
    Example request for a basic test.ping:

    % curl -sS -i \
            -H 'Content-Type: application/json' \
            -d '[{"eauth":"pam","username":"saltdev","password":"saltdev","client":"local","tgt":"*","fun":"test.ping"}]' localhost:8001

    Example response:

    HTTP/1.0 200 OK
    Content-Length: 89
    Content-Type: application/json
    {"return": [{"ms--4": true, "ms--3": true, "ms--2": true, "ms--1": true, "ms--0": true}]}

    Example request for an asyncronous test.ping:

    % curl -sS -i \
            -H 'Content-Type: application/json' \
            -d '[{"eauth":"pam","username":"saltdev","password":"saltdev","client":"local_async","tgt":"*","fun":"test.ping"}]' localhost:8001

    Example response:

    HTTP/1.0 200 OK
    Content-Length: 103
    Content-Type: application/json
    {"return": [{"jid": "20130412192112593739", "minions": ["ms--4", "ms--3", "ms--2", "ms--1", "ms--0"]}]}

    Example request for looking up a job ID:

    % curl -sS -i \
            -H 'Content-Type: application/json' \
            -d '[{"eauth":"pam","username":"saltdev","password":"saltdev","client":"runner","fun":"jobs.lookup_jid","jid":"20130412192112593739"}]' localhost:8001

    Example response:

    HTTP/1.0 200 OK
    Content-Length: 89
    Content-Type: application/json
    {"return": [{"ms--4": true, "ms--3": true, "ms--2": true, "ms--1": true, "ms--0": true}]}

form lowstate
    A list of lowstate data appropriate for the client interface you are calling.

status 200
    success

status 401
    authentication required

  netapi developer reference

  Introduction to netapi modules

netapi modules generally bind to a port and start a service. They are purposefully open-ended. There could be multiple netapi modules that provide a REST interface, a module that provides an XMPP interface, or Websockets, or XMLRPC.

netapi modules are enabled by adding configuration to your master config file. Check the docs for each module to see external requirements and configuration settings.

Communication with Salt and Salt satellite projects is done by passing a list of lowstate dictionaries to a client interface. A list of available client interfaces is below. The lowstate dictionary items map to keyword arguments on the client interface.

SEE ALSO: Python client API

  Client interfaces

class saltapi.APIClient(opts)
    Provide a uniform method of accessing the various client interfaces in Salt in the form of low-data data structures. For example:

    >>> client = APIClient(__opts__)
    >>> lowstate = {'client': 'local', 'tgt': '*', 'fun': 'test.ping', 'arg': ''}
    >>> client.run(lowstate)

local(*args, **kwargs)
    Run execution modules syncronously

    Wraps salt.client.LocalClient.cmd().

Returns
    Returns the result from the execution module

local_async(*args, **kwargs)
    Run execution modules asyncronously

    Wraps salt.client.LocalClient.run_job().

Returns
    job ID

local_batch(*args, **kwargs)
    Run execution modules against batches of minions

    New in version 0.8.4.

    Wraps salt.client.LocalClient.cmd_batch()

Returns
    Returns the result from the exeuction module for each batch of returns

runner(fun, **kwargs)
    Run runner modules <all-salt.runners>

    Wraps salt.runner.RunnerClient.low().

Returns
    Returns the result from the runner module

wheel(fun, **kwargs)
    Run wheel modules

    Wraps salt.wheel.WheelClient.master_call().

Returns
    Returns the result from the wheel module

  Writing netapi modules

netapi modules, put simply, bind a port and start a service. They are purposefully open-ended and can be used to present a variety of external interfaces to Salt, and even present multiple interfaces at once.

SEE ALSO: The full list of netapi modules

  Configuration

All netapi configuration is done in the Salt master config and takes a form similar to the following:

rest_cherrypy:
  port: 8000
  debug: True
  ssl_crt: /etc/pki/tls/certs/localhost.crt
  ssl_key: /etc/pki/tls/certs/localhost.key

  The __virtual__ function

Like all module types in Salt, netapi modules go through Salt's loader interface to determine if they should be loaded into memory and then executed.

The __virtual__ function in the module makes this determination and should return False or a string that will serve as the name of the module. If the module raises an ImportError or any other errors, it will not be loaded.

  The start function

The start() function will be called for each netapi module that is loaded. This function should contain the server loop that actually starts the service. This is started in a multiprocess.

  Inline documentation

As with the rest of Salt, it is a best-practice to include liberal inline documentation in the form of a module docstring and docstrings on any classes, methods, and functions in your netapi module.

  Loader “magic” methods

The loader makes the __opts__ data structure available to any function in a netapi module.

RELEASES

  Release notes

  salt-api 0.5.0

salt-api is gearing up for the initial public release with 0.5.0. Although this release ships with working basic functionality it is awaiting the authentication backend that will be introduced in Salt 0.10.4 before it can be considered ready for testing at large.

  REST API

This release presents the flagship netapi module which provides a RESTful interface to a running Salt system. It allows for viewing minions, runners, and jobs as well as running execution modules and runners of a running Salt system through a REST API that returns JSON.

  Participation

salt-api is just getting off the ground so feedback, questions, and ideas are critical as we solidify how this project fits into the overall Salt infrastructure management stack. Please get involved by filing issues on GitHub, discussing on the mailing list, and chatting in #salt on Freenode.

  salt-api 0.6.0

salt-api inches closer to prime-time with 0.6.0. This release adds the beginnings of a universal interface for accessing Salt components via the tried and true method of passing low-data to functions (a core component of Salt's remote execution and state management).

  Low-data interface

A new view accepts :http:post: requests at the root URL that accepts raw low-data as :http:post: data and passes that low-data along to a client interface in Salt. Currently only LocalClient and RunnerClient interfaces have been implemented in Salt with more coming in the next Salt release.

  External authentication

Raw low-data can contain authentication credentials that make use of Salt's new external_auth system.

The following is a proof-of-concept of a working eauth call. (It bears repeating this is a pre-alpha release and this should not be used by anyone for anything real.)

% curl -si localhost:8000 \
    -d client=local \
    -d tgt='*' \
    -d fun='test.ping' \
    -d arg \
    -d eauth=pam \
    -d username=saltdev \
    -d password=saltdev

  Participation

salt-api is just getting off the ground so feedback, questions, and ideas are critical as we solidify how this project fits into the overall Salt infrastructure management stack. Please get involved by filing issues on GitHub, discussing on the mailing list, and chatting in #salt-devel on Freenode.

  salt-api 0.7.0

salt-api is ready for alpha-testing in the real world. This release solidifies how salt-api will communicate with the larger Salt ecosystem. In addition authentication and encryption (via SSL) have been added.

The first netapi module was a proof of concept written in Flask. It was quite useful to be able to quickly hammer out a URL structure and solidify on an interface for programmatically calling out to Salt components. As of this release that module has been deprecated and removed in favor of a netapi module written in CherryPy. CherryPy affords tremendous flexibility when composing a REST interface and will present a stable platform for building out a very adaptable and featureful REST API—also we're using the excellent and fast CherryPy webserver for securely serving the API.

  Low-data interface

The last release introduced a proof-of-concept for how the various Salt components will communicate with each other. This is done by passing a data structure to a client interface. This release expands on that. There are currently three client interfaces in Salt.

SEE ALSO: netapi-introduction

  Encryption and authentication

Encryption has been added via SSL. You can supply an existing certificate or generate a self-signed certificate through Salt's tls module.

Authentication is performed through Salt's incredibly flexible external auth system and is maintained when accessing the API via session tokens.

  Participation

salt-api is just getting off the ground so feedback, questions, and ideas are critical as we solidify how this project fits into the overall Salt infrastructure management stack. Please get involved by filing issues on GitHub, discussing on the mailing list, and chatting in #salt-devel on Freenode.

  salt-api 0.7.5

This release is a mostly a minor release to pave a better path for salt-ui though there are some small feature additions and bugfixes.

  Changes

•   Convenience URLs /minions and /jobs have been added as well as a async client wrapper. This starts a job and immediately returns the job ID, allowing you to fetch the result of that job at a later time.

•   The return format will now default to JSON if no specific format is requested.

•   A new setting static has been added that will serve any static media from the directory specified. In addition if an index.html file is found in that directory and the Accept header in the request prefer HTML that file will be served.

•   All HTML, including the login form, has been removed from salt-api and moved into the salt-ui project.

•   Sessions now live as long as the Salt token.

  Participation

salt-api is just getting off the ground so feedback, questions, and ideas are critical as we solidify how this project fits into the overall Salt infrastructure management stack. Please get involved by filing issues on GitHub, discussing on the mailing list, and chatting in #salt-devel on Freenode.

  salt-api 0.8.0

We are happy to announce the release of salt-api 0.8.0.

This release encompasses bugfixes and new features for the rest_cherrypy netapi module that provides a RESTful interface for a running Salt system.

NOTE: Requires Salt 0.13

  Changes

In addition to the usual documentation improvements and bug fixes this release introduces the following changes and additions.

Please note the backward incompatible change detailed below.

  RPM packaging

Thanks to Andrew Niemantsvedriet (@kaptk2) salt-api is now available in Fedora package repositories as well as RHEL compatible systems via EPEL.

•   http://dl.fedoraproject.org/pub/epel/5/i386/repoview/salt-api.html

•   http://dl.fedoraproject.org/pub/epel/5/x86_64/repoview/salt-api.html

•   http://dl.fedoraproject.org/pub/epel/6/i386/repoview/salt-api.html

•   http://dl.fedoraproject.org/pub/epel/6/x86_64/repoview/salt-api.html

    Thanks also to Clint Savage (@herlo) and Thomas Spura (@tomspur) for helping with that process.

  Ubuntu PPA packaging

Thanks to Sean Channel (@seanchannel, pentabular) salt-api is available as a PPA on the SaltStack LaunchPad team.

https://launchpad.net/~saltstack/+archive/salt

  Authentication information on login

WARNING: Backward incompatible change

The /login URL no longer responds with a 302 redirect for success.

Although this is behavior is common in the browser world it is not useful from an API so we have changed it to return a 200 response in this release.

We take backward compatibility very seriously and we apologize for the inconvenience. In this case we felt the previous behavior was limiting. Changes such as this will be rare.

New in this release is displaying information about the current session and the current user. For example:

% curl -sS localhost:8000/login \
    -H 'Accept: application/x-yaml'
    -d username='saltdev'
    -d password='saltdev'
    -d eauth='pam'
return:
- eauth: pam
  expire: 1365508324.359403
  perms:
  - '@wheel'
  - grains.*
  - state.*
  - status.*
  - sys.*
  - test.*
  start: 1365465124.359402
  token: caa7aa2b9dbc4a8adb6d2e19c3e52be68995ef4b
  user: saltdev

  Bypass session handling

A convenience URL has been added (/run) to bypass the normal session-handling process.

The REST interface uses the concept of "lowstate" data to specify what function should be executed in Salt (plus where that function is and any arguments to the function). This is a thin wrapper around Salt's various "client" interfaces, for example Salt's LocalClient() which can accept authentication credentials directly.

Authentication with the REST API typically goes through the login URL and a session is generated that is tied to a Salt external_auth token. That token is then automatically added to the lowstate for subsequent requests that match the current session.

It is sometimes useful to handle authentication or token management manually from another program or script. For example:

curl -sS localhost:8000/run \
    -d client='local' \
    -d tgt='*' \
    -d fun='test.ping' \
    -d eauth='pam' \
    -d username='saltdev' \
    -d password='saltdev'

It is a Bad Idea (TM) to do this unless you have a very good reason and a well thought out security model.

  Logout

An URL has been added (/logout) that will cause the client-side to expire the session cookie and the server-side session to be invalidated.

  Running the REST interface via any WSGI-compliant server

The rest_cherrypy netapi module is a regular WSGI application written using the CherryPy framework. It was written with the intent of also running from any WSGI-compliant server such as Apache and mod_wsgi, Gunicorn, uWSGI, Nginx and FastCGI, etc.

The WSGI application entry point has been factored out into a stand-alone file in this release suitable for calling from an external server. salt-api does not need to be running in this scenario.

For example, an Apache virtual host configuration:

<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/saltapi/netapi/rest_cherrypy/wsgi.py
</VirtualHost>

  Participation

Please get involved by filing issues on GitHub, discussing on the mailing list, and chatting in #salt-devel on Freenode.

  salt-api 0.8.2

salt-api 0.8.2 is largely a bugfix release that fixes a compatibility issue with changes in Salt 0.15.9.

NOTE: Requires Salt 0.15.9 or greater

The following changes have been made to the rest_cherrypy netapi module that provides a RESTful interface for a running Salt system:

•   Fixed issue #87 which caused the Salt master's PID file to be overwritten.

•   Fixed an inconsistency with the return format for the /minions convenience URL.

    WARNING: This is a backward incompatible change.

•   Added a dedicated URL for serving an HTML app

•   Added dedicated URL for serving static media

  salt-api 0.8.3

salt-api 0.8.3 is a small release largely concerning changes and fixes to the rest_cherrypy netapi module.

This release will likely be the final salt-api release as a separate project. The Salt team has begun the process of merging this project directly in to the main Salt project. What this means for end users is only that there will be one fewer package to install. Salt itself will ship with the current netapi modules and the API and configuration will remain otherwise unchanged.

The reasoning behind merging the two projects is simply to lower the barrier to entry. Having a separate project was useful for experimentation and exploration but there was no technical reason for the separation -- salt-api uses the same flexible module system that Salt uses and those modules will simply be moved into Salt.

Going forward, Salt will ship with the same REST interface that salt-api currently provides. This will have the side benefit of not having to coordinate incompatible Salt and salt-api releases.

  rest_cherrypy changes

An HTTP stream of Salt's event bus has been added. This stream conforms to the SSE (Server Sent Events) spec and is easily consumed via JavaScript clients. This HTTP stream allows a real-time window into a running Salt system. A client watching the stream can see as soon as individual minions return data for a job, authentication events, and any other events that go through the Salt master.

A new configuration option to only allow access to whitelisted IP addresses. Of course, IP addresses can be easily spoofed so this feature should be thought of as a usability addition and not used for security purposes.

An option to disable SSL has been added. Previously SSL could only be disabled while running the HTTP server with debugging options enabled. Now each item can be enabled or disabled independently of the other.

In addition, there has been several bug fixes, packaging fixes, and minor code simplification.

  salt-api 0.8.4

salt-api 0.8.4 sees a number of new features and feature enhancements in the rest_cherrypy netapi module.

Work to merge salt-api into the main Salt distribution continues and it is likely to be included in Salt's Helium release.

  rest_cherrypy changes

  Web hooks

This release adds a new URL /hook that allows salt-api to serve as a generic web hook interface for Salt. POST requests to the URL trigger events on Salt's event bus.

External services like Amazon SNS, Travis CI, GitHub, etc can easily send signals through Salt's Reactor.

The following HTTP call will trigger the following Salt event.

% curl -sS http://localhost:8000/hook/some/tag \
    -d some='Data!'

Event tag: salt/netapi/hook/some/tag. Event data:

{
  "_stamp": "2014-04-04T12:14:54.389614",
  "post": {
    "some": "Data!"
  },
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "localhost:8000",
    "User-Agent": "curl/7.32.0",
    "Accept": "*/*",
    "Content-Length": "10",
    "Remote-Addr": "127.0.0.1"
  }
}

  Batch mode

The local_batch() client exposes Salt's batch mode for executing commands on incremental subsets of minions.

  Tests!

We have added the necessary framework for testing the rest_cherrypy module and this release includes a number of both unit and integration tests. The suite can be run with the following command:

python -m unittest discover -v

  CherryPy server stats and configuration

A number of settings have been added to better configure the performance of the CherryPy web server. In addition, a new URL /stats has been added to expose metrics on the health of the CherryPy web server.

  Improvements for running with external WSGI servers

Running the rest_cherrypy module via a WSGI-capable server such as Apache or Nginx can be tricky since the user the server is running as must have permission to access the running Salt system. This release eases some of those restrictions by accessing Salt's key interface through the external auth system. Read access to the Salt configuration is required for the user the server is running as and everything else should go through external auth.

  More information in the jobs URLs

The output for the /jobs/ has been augmented with more information about the job such as which minions are expected to return for that job. This same output will be added to the other salt-api URLs in the next release.

  Improvements to the Server Sent Events stream

Event tags have been added to the HTTP event stream as SSE tags which allows JavaScript or other consumers to more easily match on certain tags without having to inspect the whole event.

REFERENCE

•   genindex

•   modindex

•   search

•   glossary

AUTHOR
Thomas S. Hatch <thatch45@gmail.com> and many others, please see the Authors file

COPYRIGHT
2012, Thomas S. Hatch