Add SSL cert and key validation

This commit is contained in:
Joseph Schorr 2015-02-05 13:06:56 -05:00
parent 1255cb94ea
commit 400ffa73e6
5 changed files with 67 additions and 0 deletions

View file

@ -3,7 +3,10 @@ import os
import json
import ldap
import peewee
import OpenSSL
import logging
from fnmatch import fnmatch
from data.users import LDAPConnection
from flask import Flask
from flask.ext.mail import Mail, Message
@ -13,6 +16,8 @@ from app import app, CONFIG_PROVIDER
from auth.auth_context import get_authenticated_user
from util.oauth import GoogleOAuthConfig, GithubOAuthConfig
logger = logging.getLogger(__name__)
SSL_FILENAMES = ['ssl.cert', 'ssl.key']
def get_storage_provider(config):
@ -35,6 +40,7 @@ def validate_service_for_config(service, config):
'status': True
}
except Exception as ex:
logger.exception('Validation exception')
return {
'status': False,
'reason': str(ex)
@ -150,6 +156,50 @@ def _validate_ssl(config):
if not CONFIG_PROVIDER.volume_file_exists(filename):
raise Exception('Missing required SSL file: %s' % filename)
with CONFIG_PROVIDER.get_volume_file(SSL_FILENAMES[0]) as f:
cert_contents = f.read()
# Validate the certificate.
try:
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_contents)
except:
raise Exception('Could not parse certificate file. Is it a valid PEM certificate?')
if cert.has_expired():
raise Exception('The specified SSL certificate has expired.')
private_key_path = None
with CONFIG_PROVIDER.get_volume_file(SSL_FILENAMES[1]) as f:
private_key_path = f.name
if not private_key_path:
# Only in testing.
return
# Validate the private key with the certificate.
context = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
context.use_certificate(cert)
try:
context.use_privatekey_file(private_key_path)
except:
raise Exception('Could not parse key file. Is it a valid PEM private key?')
try:
context.check_privatekey()
except OpenSSL.SSL.Error as e:
raise Exception('SSL key failed to validate: %s' % str(e))
# Verify the hostname matches the name in the certificate.
common_name = cert.get_subject().commonName
if common_name is None:
raise Exception('Missing CommonName (CN) from SSL certificate')
if not fnmatch(config['SERVER_HOSTNAME'], common_name):
raise Exception('CommonName (CN) "%s" in SSL cert does not match server hostname "%s"' %
(common_name, config['SERVER_HOSTNAME']))
def _validate_ldap(config):
""" Validates the LDAP connection. """