Last Updated: February 25, 2016
· mcansky

Basic usage of Salt-API

As I am diving in the new job I have the opportunity to dig deeper into devops. I have been introduced to SaltStack some months ago and I have to say that while the documentation is quite limited the tool and libraries linked to it are quite impressive.

I want to automate deployment tasks and I cannot imagine connecting to a server using ssh and issuing commands from there. It has to be automatic. Salt has been grafted a web api some time ago so it looks like a good way to automate some salt calls from another app.

This short post will describe just the quick way to get it running and responding.

Installing salt-api

On the salt-master install the salt-api package. I had no difficulty to find it on my DigitalOcean server using the salt ppa repository.

Once it's done you need to configure at least a port and the authentication methods. I have decided to use a separate file to define those and include that file in the master config :

# .. master config extract
include: /etc/salt/ 
# /

And in that saltapi file we will find this :
- .*

port: 8080
debug: True

This define a user, the way the api is run (rest_cherrypy, there is another way check the docs), a port and the debug mode. The user is named saltdev, it's a system user.

Then you need to start the salt-api service (in addition to the salt-master one yes).

Actually using it

This API uses a token to manage the AUTH, you need to do a POST on /login first with the user credentials to get a token back :

curl -si localhost:8080/login \
        -H "Accept: application/json" \
        -d username='saltdev' \
        -d password='saltpass' \
        -d eauth='pam' > /tmp/cookies.txt

You can see that the response's body is stored in a text file. It will come handy at the next step. The response body looks like this :

HTTP/1.1 200 OK
Content-Length: 174
Vary: Accept-Encoding
X-Auth-Token: 0782d4a51c28da79b38420648aca5695a1952e65
Date: Sat, 24 Aug 2013 21:53:24 GMT
Access-Control-Allow-Origin: *
Server: CherryPy/3.2.2
Content-Type: application/json
Set-Cookie: session_id=0782d4a51c28da79b38420648aca5695a1952e65; expires=Sun, 25 Aug 2013 07:53:24 GMT; Path=/

{"return": [{"perms": [".*"], "start": 1377381204.210399, "token": "0782d4a51c28da79b38420648aca5695a1952e65", "expire": 1377424404.2104, "user": "saltdev", "eauth": "pam"}]}
## and stored :

# Netscape HTTP Cookie File
# This file was generated by libcurl! Edit at your own risk.

localhost       FALSE   /       FALSE   1377416205      session_id      6d2db01121e27beb39c1c11828d0cacf0c8f3c02

Once you have that token you can pass it back to curl in the next calls where you are actually doing something. Here we ping the minions (yes you need at least a minion to see a result) :

curl -b /tmp/cookies.txt -si localhost:8080/ \
    -H "Accept: application/json" \
    -d client='local' -d tgt='*' -d fun=''

Which replies with :

HTTP/1.1 200 OK
Content-Length: 34
Vary: Accept-Encoding
Server: CherryPy/3.2.2
Cache-Control: private
Date: Sat, 24 Aug 2013 21:58:23 GMT
Access-Control-Allow-Origin: *
Content-Type: application/json
Set-Cookie: session_id=0782d4a51c28da79b38420648aca5695a1952e65; expires=Sun, 25 Aug 2013 07:58:23 GMT; Path=/

{"return": [{"a-brentaal": true}]}

Using that

Now it's a matter of checking the documentation to see the complete list of calls you can do and then write a proper module in your app to talk to your minions from it.


Have fun.