Keystone token signing suffers from Highlander Syndrome. When it comes to Token Signers:
Specifically, the endpoint running keystoneclient.middleware.auth_token in its stack specifies the auth_url of the Keystone server, and that is the assumed signatory of all the tokens.
There are some shortcomings to this problem. For example, it means that a high-availability mechanism for Keystone requires each Keystone server to share the private keys and certificates used to sign the tokens. Here are some problems with this approach:
- It contrasts with the best practice of “The Private Keys never leave the system.”
- Once Keystone move to ephemeral tokens (topic for another post) Keystone servers will not need to share a token backend at all. It seems silly to then force them to share a signing certificate.
- Ideally, the signature would be distinct enough for audit purposes that we could figure out which server signed it.
There are other reasons, too. For example, a deployment might have a rule that states that different domains are managed on different Keystone servers. The certificate should enforce the identity of the signing system. So a Keystone server for Domain 1 could not sign tokens for a project in Domain 2.
From this we can deduce a couple of the core requirements for the Blueprint Distributed Signing namely:
Requirement 1: The endpoint that signed the token must be directly deducible from data contained in the signed document.
Requirement 2: Keystoneclient needs to be able to convert signer info extracted from the token to a request to Keystone for the corresponding certificate.
Requirement 3:The Keystone SIMPLE_CERT Extension needs to be capable of returning a certificate for a specific endpoint.
Requirement 4:Keystoneclient needs to be able to determine if a given signer of a token is authorized to sign for the enclosed data.
Keystone is the only service that is currently using PKI and CMS to sign data, but there is no reason that the mechanism should be restricted to working only with Keystone. Group broadcast of messages in the OpenStack Messaging system is not currently secured even with the Kite server: Kite signs messages with symmetric Keys. This works well when all members of a group are trusted, but not when the identity of the message-poster must be confirmed. If a Hypervisor is compromised, it should not be able to impersonate any other critical system in the OpenStack deployment. This leads to our next requirement:
Requirement 5:Hosts that are not endpoints, but rather undercloud entities like Nova-managed hypervisors may sign tokens, and their identities must be clearly deduced from the Signing information of the document.
We don’t have all that much to play with: the Signer info of an X509 looks a lot like an X500 Distinguished Name as you might see in an LDAP query. For example, a Web server enrolled as an IPA client has the following in its server-cert stored in /etc/httpd/alias:
Creating a scheme that does not conflict with this is difficult. Ideally, it would look something like:
But this is (I am fairly certain) not a legal Subject. The CN field can’t be duplicated, and CN is not a container. I post this as a strawman: maybe we can do something fairly close to this.
For Messaging, it may make more sense for the certificates to be stored in Kite than in Keystone, but the rest of the mechanism should be identical.