With PKI, tokens have gone from 40 byte to a varying size more than 3000 bytes long. This plus additional payload in Horizon means that they no longer fit inside an HTTP cookie. How do we deal with this?
One of the design decisions in the PKI token approach was to make it a drop in replacement for UUID tokens. Initially, that was done by using the PKI token as a string where necessary. However, the SQL Alchemy back end had already defined the ID column as
sql.String(64)
Which we wanted to honor. Additionally, storing the whole token data in the backend was determined to be way too expensive. The end result was that we take a hash of the PKI token, and use that as the unique identifier. This has the property of being close enough in length to look just like a UUID token.
This same approach can be used on the web side. Horizon is configured with memcached to store the tokens. The hash serves as the key. This hash can now be stored in the secure cookie used for communication with the browser. Horizon can use the Hash to fetch the PKI token from memcached.
Horizon has a requirement that it can run without memcached as well. In that case, the hash of the token can be used in an online validate call to Keystone, just as the UUID tokens were used. The mechanism is the same.
What are the drawbacks? It means that a service needs to call to Keystone in order to validate a token if it is presented in hashed form. Thus, if Horizon tosses all of the PKI info, and instead passes the Hash off to another service, this service, too, will need to do a call to Keystone in order to validate. Since the PKI token generation is more computationally expensive than UUID token generation, the net effect is going to be more load on Keystone. Thus, the memcached hybrid approach is probably the best approach. In addition, the only token that should be stored in the cookie is an unscoped token (I’m not fond of the term unscoped, but it is waht we have)used only to enumerate projects. Any work that Horizon needs to do on behalf of a user should result in a call to generate a new PKI token, and that token should be passed on the the other service.
I have a question about Keystone scoped and unscoped tokens. I recently realized that Keystone invalidates a token when a role is added to a user. This has a bad side effect when that same user was using Horizon. I am trying to figure out how to save and reuse the unscoped token to renew a scoped token for the user without sending the user back to the Horizon login screen. Do you have a suggestion?