Raise Error Code 008 for invalid CRLs
This commit is contained in:
parent
d6906c8504
commit
effec85cf9
@ -47,8 +47,6 @@ class AuthenticationContext:
|
|||||||
def _crl_check(self):
|
def _crl_check(self):
|
||||||
try:
|
try:
|
||||||
self.crl_cache.crl_check(self.cert)
|
self.crl_cache.crl_check(self.cert)
|
||||||
except CRLInvalidException as exc:
|
|
||||||
raise UnauthenticatedError("CRL expired. " + str(exc))
|
|
||||||
except CRLRevocationException as exc:
|
except CRLRevocationException as exc:
|
||||||
raise UnauthenticatedError("CRL check failed. " + str(exc))
|
raise UnauthenticatedError("CRL check failed. " + str(exc))
|
||||||
|
|
||||||
|
@ -2,9 +2,13 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from flask import current_app as app
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from OpenSSL import crypto, SSL
|
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):
|
def get_common_name(x509_name_object):
|
||||||
for comp in x509_name_object.get_components():
|
for comp in x509_name_object.get_components():
|
||||||
@ -176,9 +180,10 @@ class CRLCache(CRLInterface):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
except crypto.X509StoreContextError as err:
|
except crypto.X509StoreContextError as err:
|
||||||
if (
|
if err.args[0][0] == CRL_EXPIRED_ERROR_CODE:
|
||||||
err.args[0][2] == "CRL has expired"
|
if app.config.get("CRL_FAIL_OPEN"):
|
||||||
): # there has to be a better way than this
|
return True
|
||||||
|
else:
|
||||||
raise CRLInvalidException("CRL expired. Args: {}".format(err.args))
|
raise CRLInvalidException("CRL expired. Args: {}".format(err.args))
|
||||||
raise CRLRevocationException(
|
raise CRLRevocationException(
|
||||||
"Certificate revoked or errored. Error: {}. Args: {}".format(
|
"Certificate revoked or errored. Error: {}. Args: {}".format(
|
||||||
|
@ -8,6 +8,7 @@ from atst.domain.invitations import (
|
|||||||
ExpiredError as InvitationExpiredError,
|
ExpiredError as InvitationExpiredError,
|
||||||
WrongUserError as InvitationWrongUserError,
|
WrongUserError as InvitationWrongUserError,
|
||||||
)
|
)
|
||||||
|
from atst.domain.authnid.crl import CRLInvalidException
|
||||||
from atst.domain.portfolios import PortfolioError
|
from atst.domain.portfolios import PortfolioError
|
||||||
from atst.utils.flash import formatted_flash as flash
|
from atst.utils.flash import formatted_flash as flash
|
||||||
|
|
||||||
@ -32,6 +33,11 @@ def make_error_pages(app):
|
|||||||
def not_found(e):
|
def not_found(e):
|
||||||
return handle_error(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)
|
@app.errorhandler(exceptions.UnauthenticatedError)
|
||||||
# pylint: disable=unused-variable
|
# pylint: disable=unused-variable
|
||||||
def unauthorized(e):
|
def unauthorized(e):
|
||||||
|
@ -56,12 +56,9 @@ def test_expired_crl_check_fails():
|
|||||||
auth_context = AuthenticationContext(
|
auth_context = AuthenticationContext(
|
||||||
MockCRLCache(valid=False, expired=True), "SUCCESS", DOD_SDN, CERT
|
MockCRLCache(valid=False, expired=True), "SUCCESS", DOD_SDN, CERT
|
||||||
)
|
)
|
||||||
with pytest.raises(UnauthenticatedError) as excinfo:
|
with pytest.raises(CRLInvalidException) as excinfo:
|
||||||
assert auth_context.authenticate()
|
assert auth_context.authenticate()
|
||||||
|
|
||||||
(message,) = excinfo.value.args
|
|
||||||
assert "CRL expired" in message
|
|
||||||
|
|
||||||
|
|
||||||
def test_bad_sdn():
|
def test_bad_sdn():
|
||||||
auth_context = AuthenticationContext(MockCRLCache(), "SUCCESS", "abc123", CERT)
|
auth_context = AuthenticationContext(MockCRLCache(), "SUCCESS", "abc123", CERT)
|
||||||
|
@ -6,6 +6,7 @@ from .mocks import DOD_SDN_INFO, DOD_SDN, FIXTURE_EMAIL_ADDRESS
|
|||||||
from atst.domain.users import Users
|
from atst.domain.users import Users
|
||||||
from atst.domain.roles import Roles
|
from atst.domain.roles import Roles
|
||||||
from atst.domain.exceptions import NotFoundError
|
from atst.domain.exceptions import NotFoundError
|
||||||
|
from atst.domain.authnid.crl import CRLInvalidException
|
||||||
from atst.domain.auth import UNPROTECTED_ROUTES
|
from atst.domain.auth import UNPROTECTED_ROUTES
|
||||||
from .factories import UserFactory
|
from .factories import UserFactory
|
||||||
|
|
||||||
@ -211,3 +212,15 @@ def test_redirected_on_login(client, monkeypatch):
|
|||||||
target_route = url_for("users.user")
|
target_route = url_for("users.user")
|
||||||
response = _login(client, next=target_route)
|
response = _login(client, next=target_route)
|
||||||
assert target_route in response.headers.get("Location")
|
assert target_route in response.headers.get("Location")
|
||||||
|
|
||||||
|
|
||||||
|
def test_error_on_invalid_crl(client, monkeypatch):
|
||||||
|
def _raise_crl_error(*args):
|
||||||
|
raise CRLInvalidException()
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"atst.domain.authnid.AuthenticationContext.authenticate", _raise_crl_error
|
||||||
|
)
|
||||||
|
response = _login(client)
|
||||||
|
assert response.status_code == 401
|
||||||
|
assert "Error Code 008" in response.data.decode()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user