Bearer tokens are vulnerable to replay attacks. OK, so what are our options? Something where the user proves, via cryptography that they have the right to actually use the token. It doesn’t matter if it is X509, Kerberos, or something we cook up ourselves, it is going to resolve to proving you have the right to use that token.
If tokens must be validated by the owner, we effectively break the ability of Open Stack to hand around bearer tokens to get work done. We are going to have to get a lot of stuff right in order to keep from breaking things. Fortunately, we now have the tools to work around this, and to better secure an OpenStack system: Trusts and Role Based Access Control.
The use case I came up with was “create VM from CLI in a very simplified state.
The actors here are
1. Me, the end user (ayoung with multiple roles in the project younglogic)
2. Keystone
3. Nova API
4. Quantum
5. Glance
6. Swift
7. Nova Compute
We’ll lump all of Quantum’s, Swift’s, and Glance’s separate components together for now.
So I run the CLI command saying “create me a new virtual machine.” At this point, what do I have? I have an unscoped token from Keystone that allows horizon to list my projects, and I probably have a scoped token from keystone with my roles in the younglogic project. Lets assume that there are not transferable: any action I take will get signed by me, and if the service that I pass my token on to needs to call another it won’t be able to use my token. It will have to use its own.
So the token that I’ve gotten out of keystone goes to Nova. The first thing that Nova needs to do is move the image from Glance to the Nova Compute. Nova needs a token the will give it permission to do that. Say that API is protected by the role “Consumes Images” I need to create a trust for the Nova server with:
{trustor=ayoung, trustee=nova-api,project=younglogic,roles=[“Consumes Images”]} I probably should give it a relatively short time out: say an hour, as we might be queued up. Impersonation is not required, as this is done at the project level.
Glance already has a trust set up for me to talk to swift. That trust allows the glance service user to access all of my images. Since the images are store by users and not by projects the glance trust is an impersonation trust. How does glance know to use this trust for images in my project when the request came in from the Nova user? Good question, and it is an issue yet to be resolved. But a mapping is possible.
Now nova needs to push the image to nova-compute. Again, this is done via the trust token, and it probably makes sense that the same role, “Consumes Images” be used to push the image to the compute node. While Nova Compute may trust Nova API, by using the trust, we assure that the resources are assigned to the project.
Now we have to go to Quantum and add the new IP address to the network for this Virtual machine. Again, we can use the “Consumes Images” role, but that seems a little specific. Probably more correct to give a role along the lines of “Modifies Network Addresses” as that role could be used for many things. However, both of these roles could be on the initial trust token. So {trustor=ayoung, trustee=nova-api,project=younglogic,roles=[“Consumes Images”,”Modifies Network Addresses”]}
Now we need to actually create a virtual machine from the image. Lets assume that there are people that would be able to create a virtual machine only if the image was in place already, but could not deploy a new image. Thus, we will grant yet a third role “Creates VM”. And a fourth “Power Cycles VM”. It depends on the granularity of trust we want to place around the operations. So our completed token looks roughly like this:
{trustor=ayoung, trustee=nova-api,project=younglogic,roles=[“Consumes Images”,”Modifies Network Addresses”, “Creates VM”, “Power Cycles VM”], expires=now + 1 hour}
This is pseudo-code: these user IDs would be uuids and the time would be an absolute time, not relative.
Note now that it is the trust that lasts for an hour. However, we can make the tokens very short lived. The rule of thumb should be “long enough to push a request and get a response via HTTP.” In the case of Nova API making calls to Glance, Quantum, and Nova Compute, it can continue to reuse a token until it is about to expire, an the get a new one, so that if the quantum call returns immediately, it doesn’t need to get a new token before going to Nova Compute. If, on the other hand, the glance call takes 15 minutes, it only needs the token to be valid at the start of the call, and it can fetch a new token once it needs it.
This example is obviosuly the abbreviated version of what happens. There are lots of details elided for the sake of clarity. What is important is how Trusts can be used in conjunction with RBAC to provide a more secure Open Stack deployment.