SLGA: Capabilities explained (technical) - mrtopf.demrtopf.de

SLGA: Capabilities explained (technical)

One of the building blocks of the open metaverse Linden Lab is going to build via the open Second Life Grid Architecture Working Group are the so-called „Capabilities“. These are even in use already in the existing Second Life Grid but will be used even more in the future. In fact most of web services we are going to build will be encapsuled in Capabilities.

But what are Capabilities actually? To understand this we should look at how ReST based Web Services look today.

Authentication in RESTful Web Services

Usually if you want to authenticate with some website you do this via a login and this website then sets a cookie in your browser. So authentication is mainly done via a header inside the HTTP request (because the Cookie is sent in the header). If we look at the Amazon Web Services , e.g. how to create a new bucket for Amazon S3 we see a similar mechanism:

PUT / HTTP/1.1
Host: colorpictures.s3.amazonaws.com
Content-Length: 0
Date: Wed, 01 Mar  2006 12:00:00 GMT
Authorization: AWS 15B4D3461F177624206A:xQE0diMbLRepdf3YB+FIEXAMPLE=

So in this case the authorization key is sent as header field as well.

How do Capabilities work?

Capabilities are used for authorization, too. In fact they are used instead of those header fields. A capability here is simply a URL which represent the web service. It might look like this:

https://capsserrver.mydomain.com/caps/b658bd6e-ae29-11dc-83f0-0017f2c69b9c

This URL is only known to you and it allows you to call a certain web service which is hidden behind that URL. As there is a random string (a UUID in this case) is involved it is not guessable and thus can act as authorization. It also means that you do not call the web service in question directly but always via such a capability URL.
The web service behind that cap might actually resolve to something like this:

http://assetserver.local/users/tao_takashi/inventory/chair

The host assetserver.local will never be exposed to the internet in this scenario, only the caps. The caps server then takes this random string and looks up the original URL and proxies the request to that web service (the assetserver one in this case). As you can also see, your username (tao_takashi) is not transferred aswell.

How does the process run in detail?

So let me explain from the start: First you login by accessing a publically available web service on the login server. You send it your username and password and among other things you will get a seed capability back. The diagram below shows the sequence:

  1. You POST your login data to the login server
  2. The login server starts a new session on an agent host. This know you are logged in, who you are and so on.
  3. The agent host now has a web service which could be http://agenthost.local/tao_takashi/seed and it wants to grant the client a capability for that. It does that by asking the Capability Server for a capability URL for the mentioned URL (in fact tao_takashi could also be an internal session id which eventually makes more sense to be able to attach this functionality to a session).
  4. The Agent host sends the new capability URL via the login server as a response to the POST in step 1 back to the client. This seed capability might look like http://caps.domain.com/caps/18761762 (usually they are UUIDs as they are more random but shorter makes more sense here for the diagram).

Now of course you cannot do much more as you only know the seed capability URL. But this one in fact is used to ask for further capabilities as the seed capability is indirectly bound to your user session. Thus it’s all the client needs to send to the server should it need more services. Especially there is no need to send any header information containing authorization information.

Now let’s imagine we want to access an inventory item. We first need to ask the seed capability to grant us the right to access an item called „chair“ (this is simplified, of course you first need to know there is an item called „chair“ and it’s probably more likely an UUID than a name etc.). To do this we simply send a request for this new capability to the seed capability. The seed capability is received by the caps server which looks up the internal URL for that caps URL and proxies the request on (in our case to http://agenthost.local/tao_takashi/seed).


The seed cap implementation now checks if the user is allowed to use that web service. If so it does the same process as for the seed capability which means it asks the caps server to create a new capability URL for the internal URL. This might look like http://caps.comain.com/caps/99988171 for the internal URL http://assets.local/tao_takashi/chair.

In the next diagram we can see how this web service is called then:


Once again the caps server only acts as a proxy.

Please do also note that those capabilities might expire after some time. Also note that Linden Lab does not want caps with paths in them as it adds complexity in handling that path. One example might be to grant a caps just for retrieving inventory and add the actual inventory path to that (if we decide to map the folder structure of your inventory directly to a URL). Then it’s the question what happens if there is a „..“ in that path. There seem to be some concerns that this might lead to problems regarding security. Thus Linden Lab’s proposal is to grant a cap for each individual inventory item.

What are the benefits of using Capabilities vs. headers

To see the advantage we need to have a look at how things work at Linden Lab. They have a lot of components written in various languages and frameworks which would need to authenticate the user and hold session information (or access it). This means that you’d have to implement security mechanism in each of these modules. And test it of course.

Having capabilities removes that burden. Security is done in a central place, the seed capability and all those modules don’t need to even care about it. They might simply be called like http://imagehost.local/upload_image?user=TaoTakashi&data=…. from the caps server. They don’t need to check anymore if this user is really allowed to upload as this has been done before.

The question is of course how the seed cap knows what service to grant to which user. But for now this seems to be quite easy as there are not too many levels of authorization, mainly „is god because works for Linden Lab“ or „normal resident“ and thus might be denied some of the capabilities such as shutting down the grid.

If you also think about the idea that the new Second Life Grid Architecture is all about interoperability you might also want to mix parts implemented by different people inside your installation. Like the asset server could come from person X, the IM server from party Y and so on. All these parts would need to handle authorization themselves and somehow connect to the session host which knows about permissions. Or to some database. So in this case capabilities are probably easier for plugging a system together.

Of course the seed capability has to know about all the modules and how to access them with the right URL syntax. But this should be defined in the protocol anyway.

The capability server itself is also a quite simple application as it only needs to hold a mapping of internal vs. external URLs and basically two methods, one for granting a new cap and one for accessing one (which is the proxy part). Linden Lab even considers to open source this module.

What might be the drawbacks of using capabilities?

One drawback is of course the increased network traffic. For each web service you want to use you first need to ask the seed capability for permission and the caps URL. Only then can you call the web service. This means that in the end you will have 2 HTTP requests between client and server. Of course these caps URLs can be cached on the client side so you don’t need to request them again if you want to use the same web service twice. It needs to be seen how much of a problem this will be.

Then it adds complexity. People are not used to that concept and as I know from my Plone and Zope work it’s hard to get people on board if there are too many new concepts. This might be also the case for the Second Life Grid Working Group.

Another point is that the seed capability basically needs to know all the other modules and how to call them. This is maybe not such a big problem as some part needs to know about this anyway. Either the client in a header based auth scenario or the seed cap in this case. Actually maybe it’s even a benefit as you don’t need to change the client should you want to change the call definition.

Conclusion

Well, I am not yet sure how useful capabilities are and if they don’t bring us some performance constraints if they are more widely used. Of course they make sense if we look at the heterogenous part scenario above. But even here we could say that not the client asks the seed cap for permission but the module on the local network does. The client might still call something like http://assets.local/tao_takashi/chair but the web service implementation could then ask a central service on the local network for permission to use it (here of course the session id or auth key would be needed inside the header). This at least would be better for performance as these components are closer together network-wise.

I still have to think about it and some discussion would be great here. Then again Linden Lab probably wants to keep them the way they designed them for now as their priority in this project is to move the existing infrastructure to the new one at some part and they probably wouldn’t want to change too much if not really needed.

Tags: , , , , , ,

14 Kommentare » Schreibe einen Kommentar

  1. Excellent post. I'm not sure your concerns will be problems:

    * capabilities are easy to understand (thus easing adoption)

    * the seed capability can give you another seed capability into another service (solves the seed capability requiring global knowledge problem)

    – the login service gives you an agent domain seed capability

    – the agent domain seed capability gives you a region domain seed capability (if the agent chooses to enter a region)

    * capabilities are usually requested at the beginning of a "session" with some entity and then used repeatedly (thus you do not need 2 http requests per request during normal usage)

    – a user wants to log in to just group chat:

    – request the group chat seed capability from the authentication service, and then request the GetNextMessage and SendMessage capabilities from the seed cap

    – repeatedly invoke these GetNextMessage and SendMessage capabilities for the duration of the chat session with the server

    Hope this helps clear up any confusion.

    Again, excellent post, great work!

    Donovan

  2. Thanks! :-)

    Regarding performance I was wondering mostly about the inventory caps. I am not sure about their usage yet though.

    I am also not clear about adoption. I've seen this happen and every new concept as easy as it might be is a burden. And I know from my own experience that it's not that easy to understand them, esp. it took long for me to understand the caps server actually acts as a proxy (thus also my lengthy explanation). So in general I would go for the most common route unless there is really a big compelling reason for doing otherwise.

    And thanks for clearing up the details a bit more! :-)

    When is the open source release coming? :-)

  3. One concern I have is around security of the capability URL's. They not only need to be not easily guessable, but not easily discoverable. If you are not using HTTPS for the connections, then one could conceivably sniff the capability URL, and therefore gain access to that capability. For that reason, all capabilities should be accessed via https, should they not?

  4. That's indeed a concern and this is why Linden Lab said that they always should be transmitted via HTTPS.

    You mean the open source release of their Capabilities Server? No idea, will ask again today at Zero's office hours.

  5. This is an excellent article, Tao, very "tutorial".

    In AWG we learned about caps by gradual osmosis and so the understanding gradually seeped in, but for newcomers to our sessions the concept might appear quite obscure. I think this tutorial will help remedy that.

    Well done.

  6. Pingback: SLGA: Linden Lab releases Capabilities Server as Open Source (technical) — mrtopf.de

  7. Pingback: UgoTrade » Blog Archive » Open Source Virtual Worlds Pushing the Envelope

  8. Pingback: Open grids and distributed asset systems « justincc’s opensim blog

  9. Pingback: Setting up a framework for a Python implementation of the Open Grid Protocol (technical) — mrtopf.de

  10. Pingback: RANT: Sharks in the water. - Page 6 - SLUniverse Forums

  11. Pingback: RANT: Sharks in the water. - Page 7 - SLUniverse Forums

  12. Thinking some more about this capabilities architecture, getting a proxy once and use it many times is risky. The asset server doesn't validate the request anymore. So the moment someone manages to break the algorithm of going from a UUID to the URL for the asset server, anything can be asked for. This means that only stuff that is free to use for everyone can be acquired with this "get once use many" proxy.

    All other stuff needs to be done by first going to the caps server to get a proxy and then fire the request to the second server. The first call checks access and more, the second call delivers the data.

    Why not have the caps server forward the request to the asset server and returns the answer in one turn around ! This will save one network request and have the same result.

    greetings, Ben

  13. Right, the asset server does not do a check anymore.. This is intentional by Linden Lab AFAIK because they want to leave this whole security thing to one central component.
    The point here is though that the asset server is inside an internal network and cannot be reached except via this capability proxy. So as long as you cannot access the internal network you should be safe. The UUID btw is just assigned randomly and remembered inside a database in the proxy and expiring after some time. Guessing it should be quite hard.

    And yes, it's an additional request to the service to first get the UUID-mapped URL. You can retrieve multiple capabilities at once though.

    And I must say that I am also not a big fan of this. I personally would still check the request on each sub-service and having some sort of header based auth would also be easier to implement with most web frameworks. There are also mechanisms like OAuth now which are already used by many parties, have library implementations and a growing community. They might not be perfect for that job yet but changes can always be made by participating in these communities.

    Your suggestion might actually work as long as you only request one capability. But then again, why not simply put the seed cap into a header field and use this as a session and you might still be able to implement this capability mechanism internally.

    But we have to see what actually will come out of the MMOX discussion at the IETF as also Linden Lab employees are looking more at OAuth these days. A final result will take some time though.

  14. Pingback: The Thieves Motherload - Page 42 - SLUniverse Forums