unable to load certificate should abort request

If openssl returns with a command line error (3), we assume
the PKI certificate is not properly installed.  Added
'try ... except' blocks to cms_sign_text and cms_sign_token
calls.

Fixes: bug #1103569
Change-Id: Iad98738e990d3ab1ec0d0015840d76cf948ae560
This commit is contained in:
David Höppner 2013-02-22 18:43:56 +01:00
parent 1f7c863a9c
commit b1474da141
4 changed files with 56 additions and 12 deletions

View File

@ -17,6 +17,7 @@
"""Token Factory"""
import json
import subprocess
import uuid
import webob
@ -255,13 +256,17 @@ def create_token(context, auth_context, auth_info):
if CONF.signing.token_format == 'UUID':
token_id = uuid.uuid4().hex
elif CONF.signing.token_format == 'PKI':
token_id = cms.cms_sign_token(json.dumps(token_data),
CONF.signing.certfile,
CONF.signing.keyfile)
try:
token_id = cms.cms_sign_token(json.dumps(token_data),
CONF.signing.certfile,
CONF.signing.keyfile)
except subprocess.CalledProcessError:
raise exception.UnexpectedError(_(
'Unable to sign token.'))
else:
raise exception.UnexpectedError(
raise exception.UnexpectedError(_(
'Invalid value for token_format: %s.'
' Allowed values are PKI or UUID.' %
' Allowed values are PKI or UUID.') %
CONF.signing.token_format)
token_api = token_module.Manager()
try:

View File

@ -131,7 +131,12 @@ def cms_sign_text(text, signing_cert_file_name, signing_key_file_name):
output, err = process.communicate(text)
retcode = process.poll()
if retcode or "Error" in err:
LOG.error(_('Signing error: %s') % err)
if retcode == 3:
LOG.error(_("Signing error: Unable to load certificate - "
"ensure you've configured PKI with "
"'keystone-manage pki_setup'"))
else:
LOG.error(_('Signing error: %s') % err)
raise subprocess.CalledProcessError(retcode, "openssl")
return output

View File

@ -1,4 +1,5 @@
import json
import subprocess
import uuid
from keystone.common import cms
@ -114,13 +115,17 @@ class Auth(controller.V2Controller):
if CONF.signing.token_format == 'UUID':
token_id = uuid.uuid4().hex
elif CONF.signing.token_format == 'PKI':
token_id = cms.cms_sign_token(json.dumps(token_data),
CONF.signing.certfile,
CONF.signing.keyfile)
try:
token_id = cms.cms_sign_token(json.dumps(token_data),
CONF.signing.certfile,
CONF.signing.keyfile)
except subprocess.CalledProcessError:
raise exception.UnexpectedError(_(
'Unable to sign token.'))
else:
raise exception.UnexpectedError(
raise exception.UnexpectedError(_(
'Invalid value for token_format: %s.'
' Allowed values are PKI or UUID.' %
' Allowed values are PKI or UUID.') %
CONF.signing.token_format)
try:
self.token_api.create_token(

View File

@ -19,11 +19,14 @@ import os
import shutil
from keystone.common import openssl
from keystone import exception
from keystone import test
from keystone import token
ROOTDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SSLDIR = "%s/tests/ssl/" % ROOTDIR
CONF = test.CONF
DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id
def rootdir(*p):
@ -42,6 +45,29 @@ class CertSetupTestCase(test.TestCase):
CONF.signing.ca_certs = os.path.join(CERTDIR, "ca.pem")
CONF.signing.keyfile = os.path.join(KEYDIR, "signing_key.pem")
self.load_backends()
self.controller = token.controllers.Auth()
def test_can_handle_missing_certs(self):
self.opt_in_group('signing', token_format='PKI')
self.opt_in_group('signing', certfile='invalid')
user = {
'id': 'fake1',
'name': 'fake1',
'password': 'fake1',
'domain_id': DEFAULT_DOMAIN_ID
}
body_dict = {
'passwordCredentials': {
'userId': user['id'],
'password': user['password'],
},
}
self.identity_api.create_user(user['id'], user)
self.assertRaises(exception.UnexpectedError,
self.controller.authenticate,
{}, body_dict)
def test_create_certs(self):
ssl = openssl.ConfigurePKI(None, None)
ssl.run()
@ -50,5 +76,8 @@ class CertSetupTestCase(test.TestCase):
self.assertTrue(os.path.exists(CONF.signing.keyfile))
def tearDown(self):
shutil.rmtree(rootdir(SSLDIR))
try:
shutil.rmtree(rootdir(SSLDIR))
except OSError:
pass
super(CertSetupTestCase, self).tearDown()