Signed Authentication and Authorization

Openstack Keystone currently operates on-line validation for Tokens.  Once a token is issued out,  each of the systems presented with the token has to check the validity of the token with the Keystone server.  This makes Keystone the highest traffic service in an Openstack deployment.  Using Cryptographic Message Syntax (CMS) we can generated a token that can be verified using public key cryptography instead of making a network call.  Here’s a proof-of-concept example using the command line tools.

For authorization, we need a user name. For authentication, we need a tenancy and a set of roles that the user has in the tenancy.
Authorization cannot be for ever, so we need an expiration date/time. Here is a simple JSON representation of that data.

{"user": "ayoung",  
"tenant": "coop-city",  
"role": ["hallmonitor, groundskeeper"],

Note that it has the Roles listed in it. By cryptographically verifying this document, not only does it remove the need to validate the token with Keystone, but it removes the need to go back to keystone to fetch the roles. Thus, authentication and authorization information are linked in one document.

The following assumes you have a signing certificate. See the steps here to generate one if you need it.

To Sign auth_token.json run:

cmsutil -S -d alias -N ayoung -i auth_token.json -o auth_token.p7s

The signed message is put into auth_token.p7s, a file extension that alludes to the PKCS 7 standard.

This includes all of the certificates. Use a tool to view the contents in human readable form:

 /usr/lib64/nss/unsupported-tools/derdump -i auth_token.p7s

The output is big. To simply read the message back, use:

cmsutil  -D -i auth_token.p7s  -d alias/ -h1

This gives back the additional file, along with the validated signer:

SMIME: 	level=1.2; type=signedData; nsigners=1;"Adam Young"; signer0.status=GoodSignature; 
	level=1.1; type=data; 
{"user": "ayoung",  
"tenant": "coop-city",  
"role": ["hallmonitor, groundskeeper"],

To simply check if the document is valid, drop the h1 argument. If to test it against an NSS database that does not have the CA cert in it, you get:

# cmsutil  -D -i auth_token.p7s  -d altdb

signer 0 status = SigningCertNotTrusted
cmsutil: problem decoding: Peer's Certificate issuer is not recognized.

To make this usable as a replacement for the current token scheme, we could use something like Base64 encoding:

[ayoung@ayoung cmstest]$ base64 auth_token.p7s 

The break is due to how it is displayed in the browser, but that is really one long stream of characters. The value can be sent just like the current tokens, in the -X-Auth-Token header. Now a remote service can validate the token by reversing the Base64 ENCODING AND using cmsutil or the corresponding APIs.

cat auth_token.p7s.base64  | base64 -d |  cmsutil  -D -i auth_token.p7s -d alias/

There are still a few wrinkles to iron out.

  • The token is a little longer than it needs to be, due to the certificate being embedded. For Keystone, remote systems would be better off fetching the certificate once from the Keystone server, and just matching the serial number in the CMS token.
  • The current scheme of using the token in the URL would probably not work very well with the long Base64 encoding above, but that system has other known issues, and is likely to be replaced shortly with a scheme that will instead put the token into the body of the document. However, even that step will be unnecessary with certificate based verification.
  • Signing documents from Python currently requires calling out to additional processes. The Python-NSS maintainer is aware of the issue, and is looking into making a Python-appropriate set of bindings for the CMS calls in Python-NSS.
  • Since there is no revocation of the tokens, their lifespan should be kept short. 10-30 minutes is probably appropriate. The default value will require some consensus
  • Adding roles for a user will require getting an additional token. The old token will still be valid,but will not allow the user to do any actions that require the new role.
  • The code that checks roles does not currently know about the token. It will require a small amount of code changes to make sure that the token is available to this code.
  • While this scheme is backwards compatible with the current auth scheme, the reverse is not true. Short of checking the length of the token, there is no way to confirm that a token is a cryptographically signed document as opposed to the alpha-numeric cookie in current usage. One approach for transition may be to test reading the document, and, upon failure, fall back to the online protocol.

Update: Revocation will be discussed in an additional article.

2 thoughts on “Signed Authentication and Authorization

Leave a Reply

Your email address will not be published. Required fields are marked *