Verify SSL certificates at boot time

When Glance is configured to run with SSL this patch will check
that the certificate and key exist, are readable, and match each
other at boot time.  If any of the above conditions fail an friendly
error message is logged directing the operator at a solution.
Previously the keys were not checked until a client connected.

fixes bug: 1160529

Change-Id: I16975608f9ae40ac5b84b3caa52ed5f8e22f296e
This commit is contained in:
John Bresnahan 2013-03-28 11:09:19 -10:00
parent 0fc6972024
commit 28b1129753
4 changed files with 68 additions and 0 deletions

View File

@ -32,7 +32,9 @@ import os
import platform
import subprocess
import sys
import uuid
from OpenSSL import crypto
from oslo.config import cfg
from webob import exc
@ -467,3 +469,36 @@ class LazyPluggable(object):
def __getattr__(self, key):
backend = self.__get_backend()
return getattr(backend, key)
def validate_key_cert(key_file, cert_file):
try:
error_key_name = "private key"
error_filename = key_file
key_str = open(key_file, "r").read()
key = crypto.load_privatekey(crypto.FILETYPE_PEM, key_str)
error_key_name = "certficate"
error_filename = cert_file
cert_str = open(cert_file, "r").read()
cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_str)
except IOError, ioe:
raise RuntimeError(_("There is a problem with your %s "
"%s. Please verify it. Error: %s"
% (error_key_name, error_filename, ioe)))
except crypto.Error, ce:
raise RuntimeError(_("There is a problem with your %s "
"%s. Please verify it. OpenSSL error: %s"
% (error_key_name, error_filename, ce)))
try:
data = str(uuid.uuid4())
digest = "sha1"
out = crypto.sign(key, data, digest)
crypto.verify(cert, out, data, digest)
except crypto.Error, ce:
raise RuntimeError(_("There is a problem with your key pair. "
"Please verify that cert %s and key %s "
"belong together. OpenSSL error %s"
% (cert_file, key_file, ce)))

View File

@ -115,6 +115,8 @@ def get_socket(default_port):
"option value in your configuration file"))
def wrap_ssl(sock):
utils.validate_key_cert(key_file, cert_file)
ssl_kwargs = {
'server_side': True,
'certfile': cert_file,

View File

@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import StringIO
import tempfile
@ -103,3 +104,32 @@ class TestUtils(test_utils.BaseTestCase):
byte = reader.read(1)
self.assertRaises(exception.ImageSizeLimitExceeded, _consume_all_read)
def test_validate_key_cert_key(self):
var_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
'../', 'var'))
keyfile = os.path.join(var_dir, 'privatekey.key')
certfile = os.path.join(var_dir, 'certificate.crt')
utils.validate_key_cert(keyfile, certfile)
def test_validate_key_cert_no_private_key(self):
with tempfile.NamedTemporaryFile('w+') as tmpf:
self.assertRaises(RuntimeError,
utils.validate_key_cert,
"/not/a/file", tmpf.name)
def test_validate_key_cert_cert_cant_read(self):
with tempfile.NamedTemporaryFile('w+') as keyf:
with tempfile.NamedTemporaryFile('w+') as certf:
os.chmod(certf.name, 0)
self.assertRaises(RuntimeError,
utils.validate_key_cert,
keyf.name, certf.name)
def test_validate_key_cert_key_cant_read(self):
with tempfile.NamedTemporaryFile('w+') as keyf:
with tempfile.NamedTemporaryFile('w+') as keyf:
os.chmod(keyf.name, 0)
self.assertRaises(RuntimeError,
utils.validate_key_cert,
keyf.name, keyf.name)

View File

@ -36,3 +36,4 @@ Paste
passlib
jsonschema
python-keystoneclient>=0.2.0
pyOpenSSL