Thursday, March 31, 2011

Session support in the Vyatta REST API

While it may not be exactly faithful to RESTful principals, it is a good feature/option that further enhances security.

Authentication in the Vyatta REST API uses standard HTTP basic authentication (and has since day one). Vyatta uses https so the basic authentication parameters (i.e. username and password) are encapsulated within the https protocol to provide a secure channel. Since the auth is contained within each request the server is not required to maintain state (or track a session), as the username and password are presumably good forever.

The downside of this approach is that maintaining a username and password for access can be risky (see this post)


However, there also is now an extension to this concept (App mode now, OP and Conf soon). This extension allows for a temporary session key to be obtained by the client. This temporary session key has the following properties (and advantages):

-will expire after 30 minutes of inactivity
-can be used instead of basic authentication
-will be available for all commands

The main benefit is that if a temporary key has been obtained by ill-meaning ways, it's likely to have expired, which cannot be said of a username and password.

The basic operation works as follows:

-The client obtains the key using basic authentication.
-The client can now proceed to use the key to access all forms of the API
-Upon timeout the key expires and the client will receive a http code 401 (signifying login failure via the key).

Note that all commands are authenticated against this key, just as they were with basic authentication. The typical sequence follows:

vyatta@vyatta:~$ curl -k -s -i \
-H "authorization: Basic dnlhdHRhOnZ5YXR0YQ=="  \
-H "content-length:0" -X GET https://10.3.0.127/rest/app/get-key
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.2
Cache-Control: no-cache
Content-Length: 103
Date: Fri, 11 Mar 2011 20:21:18 GMT
Server: lighttpd/1.4.28

{
  "session": {
    "source": "10.3.0.127",
    "user": "vyatta",
    "key": "0A03007F9EF6CA6C"
  }
}

The key in the json response body is the new session key. This key can now be used to access the device:

vyatta@vyatta:~$ curl -k -s -i \
-H "authorization: Vyatta-Session 0A03007F9EF6CA6C"  \
-H "content-length:0" -X GET https://10.3.0.127/rest/op/ping
HTTP/1.1 200 OK
Content-Type: application/json
Vyatta-Specification-Version: 0.2
Cache-Control: no-cache
Content-Length: 99
Date: Fri, 11 Mar 2011 20:29:36 GMT
Server: lighttpd/1.4.28

{
  "action": "true",
  "help": "   Send ICMP echo request to specified "
}

After the key has expired (30 minutes after the last request):

vyatta@vyatta:~$ curl -k -s -i \
-H "authorization: Vyatta-Session 0A03007F9EF6CA6C"  \
-H "content-length:0" -X GET https://10.3.0.127/rest/op/ping/1.1.1.1
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Secure Area"
Content-Type: application/json
Vyatta-Specification-Version: 0.2
Cache-Control: no-cache
Transfer-Encoding: chunked
Date: Fri, 11 Mar 2011 21:21:38 GMT
Server: lighttpd/1.4.28

You will get the response above, which represents an unauthorized access (in this case the key has expired).

It's important to note that configuration sessions, op processes etc. are not tied to the authentication session. In other words when a session expires the configuration sessions don't expire, and the op processes will remain. They can be accessed by the user in the future through a different key.

Finally, an override mechanism is available to use the "Vyatta-Session" authorization where the time does not update. This is useful in a polling situation and the session should only update on user initiated actions.

This mechanism looks like:

vyatta@vyatta:~$ curl -k -s -i \
-H "authorization: Vyatta-Session 0A03007F9EF6CA6C"  \
-H "content-length:0" -X GET https://10.3.0.127/rest/op/ping
HTTP/1.1 200 OK
Content-Type: application/json
Pragma: no-vyatta-session-update
Vyatta-Specification-Version: 0.2
Cache-Control: no-cache
Content-Length: 99
Date: Fri, 11 Mar 2011 20:29:36 GMT
Server: lighttpd/1.4.28

{
  "action": "true",
  "help": "   Send ICMP echo request to specified "
}

The Pragma forces the server to skip the server timestamp update.

That's it. Both authentication methods are equally available--therefore it's up to the developer to select the mechanism that works best, weighing security and application behavior.

2 comments:

  1. Hello,
    with which version do you use the API?

    ReplyDelete
  2. It's in the VSE version (not the VC or community version). But has been in the product for a while now (don't recall which version it first showed up in).

    ReplyDelete