Merge pull request #700 from dod-ccpo/crl-failover

CRL Failover Config
This commit is contained in:
montana-mil
2019-03-15 14:56:03 -04:00
committed by GitHub
9 changed files with 254 additions and 125 deletions

View File

@@ -142,6 +142,7 @@ def map_config(config):
"RQ_REDIS_URL": config["default"]["REDIS_URI"],
"RQ_QUEUES": [config["default"]["RQ_QUEUES"]],
"DISABLE_CRL_CHECK": config.getboolean("default", "DISABLE_CRL_CHECK"),
"CRL_FAIL_OPEN": config.getboolean("default", "CRL_FAIL_OPEN"),
}

View File

@@ -1,7 +1,7 @@
from atst.domain.exceptions import UnauthenticatedError, NotFoundError
from atst.domain.users import Users
from .utils import parse_sdn, email_from_certificate
from .crl import CRLRevocationException
from .crl import CRLRevocationException, CRLInvalidException
class AuthenticationContext:

View File

@@ -2,9 +2,13 @@ import sys
import os
import re
import hashlib
from flask import current_app as app
from datetime import datetime
from OpenSSL import crypto, SSL
# error codes from OpenSSL: https://github.com/openssl/openssl/blob/2c75f03b39de2fa7d006bc0f0d7c58235a54d9bb/include/openssl/x509_vfy.h#L111
CRL_EXPIRED_ERROR_CODE = 12
def get_common_name(x509_name_object):
for comp in x509_name_object.get_components():
@@ -16,6 +20,12 @@ class CRLRevocationException(Exception):
pass
class CRLInvalidException(Exception):
# CRL expired
# CRL missing
pass
class CRLInterface:
def __init__(self, *args, logger=None, **kwargs):
self.logger = logger
@@ -111,7 +121,7 @@ class CRLCache(CRLInterface):
issuer_name = get_common_name(issuer)
if not crl_info:
raise CRLRevocationException(
raise CRLInvalidException(
"Could not find matching CRL for issuer with Common Name {}".format(
issuer_name
)
@@ -170,6 +180,16 @@ class CRLCache(CRLInterface):
return True
except crypto.X509StoreContextError as err:
if err.args[0][0] == CRL_EXPIRED_ERROR_CODE:
if app.config.get("CRL_FAIL_OPEN"):
self._log_info(
"Encountered expired CRL for certificate with CN {} and issuer CN {}, failing open.".format(
parsed.get_subject().CN, parsed.get_issuer().CN
)
)
return True
else:
raise CRLInvalidException("CRL expired. Args: {}".format(err.args))
raise CRLRevocationException(
"Certificate revoked or errored. Error: {}. Args: {}".format(
type(err), err.args

View File

@@ -8,6 +8,7 @@ from atst.domain.invitations import (
ExpiredError as InvitationExpiredError,
WrongUserError as InvitationWrongUserError,
)
from atst.domain.authnid.crl import CRLInvalidException
from atst.domain.portfolios import PortfolioError
from atst.utils.flash import formatted_flash as flash
@@ -32,6 +33,11 @@ def make_error_pages(app):
def not_found(e):
return handle_error(e)
@app.errorhandler(CRLInvalidException)
# pylint: disable=unused-variable
def missing_crl(e):
return handle_error(e, message="Error Code 008", code=401)
@app.errorhandler(exceptions.UnauthenticatedError)
# pylint: disable=unused-variable
def unauthorized(e):