Esempio n. 1
0
 def setUp(self):
     """ setup unittest """
     models_mock = MagicMock()
     models_mock.acme.db_handler.DBstore.return_value = FakeDBStore
     modules = {'acme.db_handler': models_mock}
     patch.dict('sys.modules', modules).start()
     import logging
     logging.basicConfig(level=logging.CRITICAL)
     self.logger = logging.getLogger('test_a2c')
     from acme.challenge import Challenge
     self.challenge = Challenge(False, 'http://tester.local', self.logger)
def chall(environ, start_response):
    """ create new account """
    with Challenge(DEBUG, get_url(environ), LOGGER) as challenge:
        if environ['REQUEST_METHOD'] == 'POST':

            request_body = get_request_body(environ)
            response_dic = challenge.parse(request_body)

            # create header
            headers = create_header(response_dic)
            start_response('{0} {1}'.format(response_dic['code'], HTTP_CODE_DIC[response_dic['code']]), headers)

            # logging
            logger_info(LOGGER, environ['REMOTE_ADDR'], environ['PATH_INFO'], response_dic)
            return [json.dumps(response_dic['data']).encode('utf-8')]

        elif environ['REQUEST_METHOD'] == 'GET':

            response_dic = challenge.get(get_url(environ, True))

            # generate header
            headers = [('Content-Type', 'application/json')]
            # create the response
            start_response('{0} {1}'.format(response_dic['code'], HTTP_CODE_DIC[response_dic['code']]), headers)

            # logging
            logger_info(LOGGER, environ['REMOTE_ADDR'], environ['PATH_INFO'], response_dic)
            # send response
            return [json.dumps(response_dic['data']).encode('utf-8')]

        else:
            start_response('405 {0}'.format(HTTP_CODE_DIC[405]), [('Content-Type', 'application/json')])
            return [json.dumps({'status':405, 'message':HTTP_CODE_DIC[405], 'detail': 'Wrong request type. Expected POST.'}).encode('utf-8')]
Esempio n. 3
0
def chall(request):
    """ challenge command """
    with Challenge(DEBUG, get_url(request.META), LOGGER) as challenge:
        if request.method == 'POST':
            response_dic = challenge.parse(request.body)
            # create the response
            response = JsonResponse(status=response_dic['code'],
                                    data=response_dic['data'])
            # generate additional header elements
            for element in response_dic['header']:
                response[element] = response_dic['header'][element]

            # logging
            logger_info(LOGGER, request.META['REMOTE_ADDR'],
                        request.META['PATH_INFO'], response_dic)
            # send response
            return response
        elif request.method == 'GET':
            response_dic = challenge.get(request.build_absolute_uri())
            # create the response
            response = JsonResponse(status=response_dic['code'],
                                    data=response_dic['data'])

            # logging
            # logger_info(LOGGER, request.META['REMOTE_ADDR'], request.META['PATH_INFO'], response_dic)
            # send response
            return response
        else:
            return JsonResponse(status=405,
                                data={
                                    'status': 405,
                                    'message': 'Method Not Allowed',
                                    'detail':
                                    'Wrong request type. Expected POST.'
                                })
Esempio n. 4
0
    def authz_info(self, url):
        """ return authzs information """
        self.logger.debug('Authorization.info({0})'.format(url))
        authz_name = url.replace(
            '{0}{1}'.format(self.server_name, self.path_dic['authz_path']), '')
        expires = uts_now() + self.expiry
        token = generate_random_string(self.logger, 32)
        authz_info_dic = {}
        if self.dbstore.authorization_lookup('name', authz_name):

            # update authorization with expiry date and token (just to be sure)
            self.dbstore.authorization_update({
                'name': authz_name,
                'token': token,
                'expires': expires
            })
            authz_info_dic['expires'] = uts_to_date_utc(expires)

            # get authorization information from db to be inserted in message
            tnauth = None
            auth_info = self.dbstore.authorization_lookup(
                'name', authz_name, ['status__name', 'type', 'value'])
            if auth_info:
                authz_info_dic['status'] = auth_info[0]['status__name']
                authz_info_dic['identifier'] = {
                    'type': auth_info[0]['type'],
                    'value': auth_info[0]['value']
                }
                if auth_info[0]['type'] == 'TNAuthList':
                    tnauth = True
            challenge = Challenge(self.debug, self.server_name, self.logger,
                                  expires)
            authz_info_dic['challenges'] = challenge.new_set(
                authz_name, token, tnauth)

        self.logger.debug('Authorization.authz_info() returns: {0}'.format(
            json.dumps(authz_info_dic)))
        return authz_info_dic
Esempio n. 5
0
    def _authz_info(self, url):
        """ return authzs information """
        self.logger.debug('Authorization._authz_info({0})'.format(url))
        authz_name = url.replace('{0}{1}'.format(self.server_name, self.path_dic['authz_path']), '')
        expires = uts_now() + self.validity
        token = generate_random_string(self.logger, 32)
        authz_info_dic = {}

        # lookup authorization based on name
        try:
            authz = self.dbstore.authorization_lookup('name', authz_name)
        except BaseException as err_:
            self.logger.critical('acme2certifier database error in Authorization._authz_info(): {0}'.format(err_))
            authz = None

        if authz:
            # update authorization with expiry date and token (just to be sure)
            try:
                self.dbstore.authorization_update({'name' : authz_name, 'token' : token, 'expires' : expires})
            except BaseException as err_:
                self.logger.critical('acme2certifier database error in Authorization._authz_info(): {0}'.format(err_))
            authz_info_dic['expires'] = uts_to_date_utc(expires)

            # get authorization information from db to be inserted in message
            tnauth = None
            try:
                auth_info = self.dbstore.authorization_lookup('name', authz_name, ['status__name', 'type', 'value'])
            except BaseException as err_:
                self.logger.critical('acme2certifier database error in Authorization._authz_info(): {0}'.format(err_))
                auth_info = {}
            if auth_info:
                if 'status__name' in auth_info[0]:
                    authz_info_dic['status'] = auth_info[0]['status__name']
                else:
                    authz_info_dic['status'] = 'pending'

                if 'type' in auth_info[0]  and 'value' in auth_info[0]:
                    authz_info_dic['identifier'] = {'type' : auth_info[0]['type'], 'value' : auth_info[0]['value']}
                    if auth_info[0]['type'] == 'TNAuthList':
                        tnauth = True

            with Challenge(self.debug, self.server_name, self.logger, expires) as challenge:
                # get challenge data (either existing or new ones)
                authz_info_dic['challenges'] = challenge.challengeset_get(authz_name, authz_info_dic['status'], token, tnauth)

        self.logger.debug('Authorization._authz_info() returns: {0}'.format(json.dumps(authz_info_dic)))
        return authz_info_dic
Esempio n. 6
0
class TestACMEHandler(unittest.TestCase):
    """ test class for ACMEHandler """
    acme = None

    def setUp(self):
        """ setup unittest """
        models_mock = MagicMock()
        models_mock.acme.db_handler.DBstore.return_value = FakeDBStore
        modules = {'acme.db_handler': models_mock}
        patch.dict('sys.modules', modules).start()
        import logging
        logging.basicConfig(level=logging.CRITICAL)
        self.logger = logging.getLogger('test_a2c')
        from acme.challenge import Challenge
        self.challenge = Challenge(False, 'http://tester.local', self.logger)

    @patch('acme.challenge.generate_random_string')
    def test_001_challenge__new(self, mock_random):
        """ test challenge generation """
        mock_random.return_value = 'foo'
        # self.order.dbstore.challenge_new.return_value = 1
        self.assertEqual(
            {
                'url': 'http://tester.local/acme/chall/foo',
                'token': 'token',
                'type': 'mtype'
            }, self.challenge._new('authz_name', 'mtype', 'token'))

    @patch('acme.challenge.generate_random_string')
    def test_002_challenge__new(self, mock_random):
        """ test challenge generation for tnauthlist challenge """
        mock_random.return_value = 'foo'
        # self.order.dbstore.challenge_new.return_value = 1
        self.assertEqual(
            {
                'url': 'http://tester.local/acme/chall/foo',
                'token': 'token',
                'type': 'tkauth-01',
                'tkauth-type': 'atc'
            }, self.challenge._new('authz_name', 'tkauth-01', 'token'))

    @patch('acme.challenge.Challenge._new')
    def test_003_challenge_new_set(self, mock_challenge):
        """ test generation of a challenge set """
        mock_challenge.return_value = {'foo': 'bar'}
        self.assertEqual([{
            'foo': 'bar'
        }, {
            'foo': 'bar'
        }, {
            'foo': 'bar'
        }], self.challenge.new_set('authz_name', 'token'))

    @patch('acme.challenge.Challenge._new')
    def test_004_challenge_new_set(self, mock_challenge):
        """ test generation of a challenge set with tnauth true """
        mock_challenge.return_value = {'foo': 'bar'}
        self.assertEqual([{
            'foo': 'bar'
        }], self.challenge.new_set('authz_name', 'token', True))

    @patch('acme.challenge.Challenge._new')
    def test_005_challenge_new_set(self, mock_challenge):
        """ test generation of a challenge set """
        mock_challenge.return_value = {'foo': 'bar'}
        self.assertEqual([{
            'foo': 'bar'
        }, {
            'foo': 'bar'
        }, {
            'foo': 'bar'
        }], self.challenge.new_set('authz_name', 'token', False))

    def test_006_challenge__info(self):
        """ test challenge.info() """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'token': 'token',
            'type': 'http-01',
            'status': 'pending'
        }
        self.assertEqual(
            {
                'status': 'pending',
                'token': 'token',
                'type': 'http-01'
            }, self.challenge._info('foo'))

    def test_007_challenge__info(self):
        """ test challenge.info()  test no "status" field in """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'token': 'token',
            'type': 'http-01',
            'validated': 'foo'
        }
        self.assertEqual({
            'token': 'token',
            'type': 'http-01'
        }, self.challenge._info('foo'))

    def test_008_challenge__info(self):
        """ test challenge.info()  test to pop "validated" key """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'token': 'token',
            'type': 'http-01',
            'status': 'pending',
            'validated': 'foo'
        }
        self.assertEqual(
            {
                'status': 'pending',
                'token': 'token',
                'type': 'http-01'
            }, self.challenge._info('foo'))

    def test_009_challenge__info(self):
        """ test challenge.info()  test to pop validated key no "status" and "validated" in """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'token': 'token',
            'type': 'http-01'
        }
        self.assertEqual({
            'token': 'token',
            'type': 'http-01'
        }, self.challenge._info('foo'))

    def test_010_challenge__info(self):
        """ test challenge.info()  test to pop "validated" key """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'token': 'token',
            'type': 'http-01',
            'status': 'valid',
            'validated': 'foo'
        }
        self.assertEqual(
            {
                'status': 'valid',
                'token': 'token',
                'type': 'http-01'
            }, self.challenge._info('foo'))

    def test_011_challenge__info(self):
        """ test challenge.info()  test to pop "validated" key """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'token': 'token',
            'type': 'http-01',
            'status': 'valid',
            'validated': 1543640400
        }
        self.assertEqual(
            {
                'status': 'valid',
                'token': 'token',
                'type': 'http-01',
                'validated': '2018-12-01T05:00:00Z'
            }, self.challenge._info('foo'))

    @patch('acme.message.Message.check')
    def test_012_challenge_parse(self, mock_mcheck):
        """ Challenge.parse() failed bcs. message check returns an error """
        mock_mcheck.return_value = (400,
                                    'urn:ietf:params:acme:error:malformed',
                                    'detail', 'protected', 'payload',
                                    'account_name')
        self.assertEqual(
            {
                'code': 400,
                'header': {},
                'data': {
                    'detail': 'detail',
                    'message': 'urn:ietf:params:acme:error:malformed',
                    'status': 400
                }
            }, self.challenge.parse('content'))

    @patch('acme.message.Message.check')
    def test_013_challenge_parse(self, mock_mcheck):
        """ Challenge.parse() failed message check returns ok but no url in protected """
        mock_mcheck.return_value = (200,
                                    'urn:ietf:params:acme:error:malformed',
                                    'detail', {
                                        'foo': 'bar'
                                    }, 'payload', 'account_name')
        self.assertEqual(
            {
                'code': 400,
                'header': {},
                'data': {
                    'detail': 'url missing in protected header',
                    'message': 'urn:ietf:params:acme:error:malformed',
                    'status': 400
                }
            }, self.challenge.parse('content'))

    @patch('acme.challenge.Challenge._name_get')
    @patch('acme.message.Message.check')
    def test_014_challenge_parse(self, mock_mcheck, mock_cname):
        """ Challenge.parse() message check returns ok with tnauhlist enabled failed tnauth check """
        self.challenge.tnauthlist_support = True
        mock_mcheck.return_value = (200, 'message', 'detail', {
            'url': 'foo'
        }, {}, 'account_name')
        mock_cname.return_value = None
        self.assertEqual(
            {
                'code': 400,
                'data': {
                    'detail': 'could not get challenge',
                    'message': 'urn:ietf:params:acme:error:malformed',
                    'status': 400
                },
                'header': {}
            }, self.challenge.parse('content'))

    @patch('acme.challenge.Challenge._info')
    @patch('acme.challenge.Challenge._name_get')
    @patch('acme.message.Message.check')
    def test_015_challenge_parse(self, mock_mcheck, mock_cname, mock_info):
        """ Challenge.parse() message check returns challenge.info() failed """
        self.challenge.tnauthlist_support = True
        mock_mcheck.return_value = (200, 'message', 'detail', {
            'url': 'foo'
        }, {}, 'account_name')
        mock_cname.return_value = 'foo'
        mock_info.return_value = {}
        self.assertEqual(
            {
                'code': 400,
                'data': {
                    'detail': 'invalid challenge: foo',
                    'message': 'urn:ietf:params:acme:error:malformed',
                    'status': 400
                },
                'header': {}
            }, self.challenge.parse('content'))

    @patch('acme.challenge.Challenge._validate_tnauthlist_payload')
    @patch('acme.challenge.Challenge._info')
    @patch('acme.challenge.Challenge._name_get')
    @patch('acme.message.Message.check')
    def test_016_challenge_parse(self, mock_mcheck, mock_cname, mock_info,
                                 mock_tnauth):
        """ Challenge.parse() with tnauhlist enabled and failed tnauth check """
        self.challenge.tnauthlist_support = True
        mock_mcheck.return_value = (200, 'message', 'detail', {
            'url': 'foo'
        }, {}, 'account_name')
        mock_cname.return_value = 'foo'
        mock_info.return_value = {'foo': 'bar'}
        mock_tnauth.return_value = (400, 'foo', 'bar')
        self.assertEqual(
            {
                'code': 400,
                'data': {
                    'detail': 'bar',
                    'message': 'foo',
                    'status': 400
                },
                'header': {}
            }, self.challenge.parse('content'))

    @patch('acme.nonce.Nonce.generate_and_add')
    @patch('acme.challenge.Challenge._validate_tnauthlist_payload')
    @patch('acme.challenge.Challenge._info')
    @patch('acme.challenge.Challenge._name_get')
    @patch('acme.message.Message.check')
    def test_017_challenge_parse(self, mock_mcheck, mock_cname, mock_cinfo,
                                 mock_tnauth, mock_nnonce):
        """ Challenge.parse() successful with TNauthlist enabled """
        self.challenge.tnauthlist_support = True
        mock_mcheck.return_value = (200,
                                    'urn:ietf:params:acme:error:malformed',
                                    'detail', {
                                        'url': 'bar'
                                    }, 'payload', 'account_name')
        mock_cname.return_value = 'foo'
        mock_cinfo.return_value = {'challenge_foo': 'challenge_bar'}
        mock_tnauth.return_value = (200, 'foo', 'bar')
        mock_nnonce.return_value = 'new_nonce'
        self.assertEqual(
            {
                'code': 200,
                'header': {
                    'Link': '<http://tester.local/acme/authz/>;rel="up"',
                    'Replay-Nonce': 'new_nonce'
                },
                'data': {
                    'challenge_foo': 'challenge_bar',
                    'url': 'bar'
                }
            }, self.challenge.parse('content'))

    @patch('acme.nonce.Nonce.generate_and_add')
    @patch('acme.challenge.Challenge._validate_tnauthlist_payload')
    @patch('acme.challenge.Challenge._info')
    @patch('acme.challenge.Challenge._name_get')
    @patch('acme.message.Message.check')
    def test_018_challenge_parse(self, mock_mcheck, mock_cname, mock_cinfo,
                                 mock_tnauth, mock_nnonce):
        """ Challenge.parse() successful with TNauthlist disabled """
        self.challenge.tnauthlist_support = False
        mock_mcheck.return_value = (200,
                                    'urn:ietf:params:acme:error:malformed',
                                    'detail', {
                                        'url': 'bar'
                                    }, 'payload', 'account_name')
        mock_cname.return_value = 'foo'
        mock_cinfo.return_value = {'challenge_foo': 'challenge_bar'}
        mock_tnauth.return_value = (200, 'foo', 'bar')
        mock_nnonce.return_value = 'new_nonce'
        self.assertEqual(
            {
                'code': 200,
                'header': {
                    'Link': '<http://tester.local/acme/authz/>;rel="up"',
                    'Replay-Nonce': 'new_nonce'
                },
                'data': {
                    'challenge_foo': 'challenge_bar',
                    'url': 'bar'
                }
            }, self.challenge.parse('content'))

    def test_019_challenge__validate_tnauthlist_payload(self):
        """ Challenge.validate_tnauthlist_payload with empty challenge_dic """
        payload = {'foo': 'bar'}
        challenge_dic = {}
        self.assertEqual((400, 'urn:ietf:params:acme:error:malformed',
                          'invalid challenge: {}'),
                         self.challenge._validate_tnauthlist_payload(
                             payload, challenge_dic))

    def test_020_challenge__validate_tnauthlist_payload(self):
        """ Challenge.validate_tnauthlist_payload with empty challenge_dic """
        payload = {}
        challenge_dic = {'type': 'foo'}
        self.assertEqual((200, None, None),
                         self.challenge._validate_tnauthlist_payload(
                             payload, challenge_dic))

    def test_021_challenge__validate_tnauthlist_payload(self):
        """ Challenge.validate_tnauthlist_payload without atc claim """
        payload = {}
        challenge_dic = {'type': 'tkauth-01'}
        self.assertEqual((400, 'urn:ietf:params:acme:error:malformed',
                          'atc claim is missing'),
                         self.challenge._validate_tnauthlist_payload(
                             payload, challenge_dic))

    def test_022_challenge__validate_tnauthlist_payload(self):
        """ Challenge.validate_tnauthlist_payload with empty atc claim """
        payload = {'atc': None}
        challenge_dic = {'type': 'tkauth-01'}
        self.assertEqual((400, 'urn:ietf:params:acme:error:malformed',
                          'SPC token is missing'),
                         self.challenge._validate_tnauthlist_payload(
                             payload, challenge_dic))

    def test_023_challenge__validate_tnauthlist_payload(self):
        """ Challenge.validate_tnauthlist_payload with '' atc claim """
        payload = {'atc': ''}
        challenge_dic = {'type': 'tkauth-01'}
        self.assertEqual((400, 'urn:ietf:params:acme:error:malformed',
                          'SPC token is missing'),
                         self.challenge._validate_tnauthlist_payload(
                             payload, challenge_dic))

    def test_024_challenge__validate_tnauthlist_payload(self):
        """ Challenge.validate_tnauthlist_payload with spc token in atc claim """
        payload = {'atc': 'a'}
        challenge_dic = {'type': 'tkauth-01'}
        self.assertEqual((200, None, None),
                         self.challenge._validate_tnauthlist_payload(
                             payload, challenge_dic))

    @patch('acme.challenge.fqdn_resolve')
    @patch('acme.challenge.url_get')
    def test_025_challenge__validate_http_challenge(self, mock_url,
                                                    mock_resolve):
        """ test Chalölenge.validate_http_challenge() with a wrong challenge """
        mock_url.return_value = 'foo'
        mock_resolve.return_value = ('foo', False)
        self.assertEqual(
            (False, False),
            self.challenge._validate_http_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))

    @patch('acme.challenge.fqdn_resolve')
    @patch('acme.challenge.url_get')
    def test_026_challenge__validate_http_challenge(self, mock_url,
                                                    mock_resolve):
        """ test Chalölenge.validate_http_challenge() with a correct challenge """
        mock_url.return_value = 'token.jwk_thumbprint'
        mock_resolve.return_value = ('foo', False)
        self.assertEqual(
            (True, False),
            self.challenge._validate_http_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))

    @patch('acme.challenge.fqdn_resolve')
    @patch('acme.challenge.url_get')
    def test_027_challenge__validate_http_challenge(self, mock_url,
                                                    mock_resolve):
        """ test Chalölenge.validate_http_challenge() without response """
        mock_url.return_value = None
        mock_resolve.return_value = ('foo', False)
        self.assertEqual(
            (False, False),
            self.challenge._validate_http_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))

    @patch('acme.challenge.fqdn_resolve')
    @patch('acme.challenge.url_get')
    def test_028_challenge__validate_http_challenge(self, mock_url,
                                                    mock_resolve):
        """ test Challenge.validate_http_challenge() failed with NX-domain error """
        mock_url.return_value = None
        mock_resolve.return_value = (None, True)
        self.assertEqual(
            (False, True),
            self.challenge._validate_http_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))

    @patch('acme.challenge.fqdn_resolve')
    @patch('acme.challenge.url_get')
    def test_029_challenge__validate_http_challenge(self, mock_url,
                                                    mock_resolve):
        """ test Chalölenge.validate_http_challenge() failed with NX-domain error - non existing case but to be tested"""
        mock_url.return_value = 'foo'
        mock_resolve.return_value = ('foo', True)
        self.assertEqual(
            (False, True),
            self.challenge._validate_http_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))

    @patch('acme.challenge.fqdn_resolve')
    @patch('acme.challenge.sha256_hash')
    @patch('acme.challenge.b64_url_encode')
    @patch('acme.challenge.txt_get')
    def test_030_challenge__validate_dns_challenge(self, mock_dns, mock_code,
                                                   mock_hash, mock_resolve):
        """ test Chalölenge.validate_dns_challenge() with incorrect response """
        mock_dns.return_value = 'foo'
        mock_code.return_value = 'bar'
        mock_hash.return_value = 'hash'
        mock_resolve.return_value = ('foo', False)
        self.assertEqual(
            (False, False),
            self.challenge._validate_dns_challenge('cert_name', 'fqdn',
                                                   'token', 'jwk_thumbprint'))

    @patch('acme.challenge.fqdn_resolve')
    @patch('acme.challenge.sha256_hash')
    @patch('acme.challenge.b64_url_encode')
    @patch('acme.challenge.txt_get')
    def test_031_challenge__validate_dns_challenge(self, mock_dns, mock_code,
                                                   mock_hash, mock_resolve):
        """ test Chalölenge.validate_dns_challenge() with correct response """
        mock_dns.return_value = 'foo'
        mock_code.return_value = 'foo'
        mock_hash.return_value = 'hash'
        mock_resolve.return_value = ('foo', False)
        self.assertEqual(
            (True, False),
            self.challenge._validate_dns_challenge('cert_name', 'fqdn',
                                                   'token', 'jwk_thumbprint'))

    @patch('acme.challenge.fqdn_resolve')
    @patch('acme.challenge.sha256_hash')
    @patch('acme.challenge.b64_url_encode')
    @patch('acme.challenge.txt_get')
    def test_032_challenge__validate_dns_challenge(self, mock_dns, mock_code,
                                                   mock_hash, mock_resolve):
        """ test Challenge.validate_dns_challenge() with invalid response """
        mock_dns.return_value = 'foo'
        mock_code.return_value = 'bar'
        mock_hash.return_value = 'hash'
        mock_resolve.return_value = (None, True)
        self.assertEqual(
            (False, True),
            self.challenge._validate_dns_challenge('cert_name', 'fqdn',
                                                   'token', 'jwk_thumbprint'))

    @patch('acme.challenge.fqdn_resolve')
    @patch('acme.challenge.sha256_hash')
    @patch('acme.challenge.b64_url_encode')
    @patch('acme.challenge.txt_get')
    def test_033_challenge__validate_dns_challenge(self, mock_dns, mock_code,
                                                   mock_hash, mock_resolve):
        """ test Challenge.validate_dns_challenge() with invalid but correct fqdn returned """
        mock_dns.return_value = 'foo'
        mock_code.return_value = 'foo'
        mock_hash.return_value = 'hash'
        mock_resolve.return_value = ('foo', True)
        self.assertEqual(
            (False, True),
            self.challenge._validate_dns_challenge('cert_name', 'fqdn',
                                                   'token', 'jwk_thumbprint'))

    def test_034_challenge__validate_tkauth_challenge(self):
        """ test Chalölenge.validate_tkauth_challenge() """
        self.assertEqual(
            (True, False),
            self.challenge._validate_tkauth_challenge('cert_name', 'fqdn',
                                                      'token',
                                                      'jwk_thumbprint',
                                                      'payload'))

    def test_035_challenge__check(self):
        """ challenge check with incorrect challenge-dictionary """
        # self.challenge.dbstore.challenge_lookup.return_value = {'token' : 'token', 'type' : 'http-01', 'status' : 'pending'}
        self.challenge.dbstore.challenge_lookup.return_value = {}
        self.assertEqual((False, False),
                         self.challenge._check('name', 'payload'))

    def test_036_challenge__check(self):
        """ challenge check with without jwk return """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__value':
            'authorization__value',
            'type':
            'type',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        self.challenge.dbstore.jwk_load.return_value = None
        self.assertEqual((False, False),
                         self.challenge._check('name', 'payload'))

    @patch('acme.challenge.Challenge._validate_http_challenge')
    @patch('acme.challenge.jwk_thumbprint_get')
    def test_037_challenge__check(self, mock_jwk, mock_chall):
        """ challenge check with with failed http challenge """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__value':
            'authorization__value',
            'type':
            'http-01',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        self.challenge.dbstore.jwk_load.return_value = 'pub_key'
        mock_chall.return_value = (False, 'foo')
        mock_jwk.return_value = 'jwk_thumbprint'
        self.assertEqual((False, 'foo'),
                         self.challenge._check('name', 'payload'))

    @patch('acme.challenge.Challenge._validate_http_challenge')
    @patch('acme.challenge.jwk_thumbprint_get')
    def test_038_challenge__check(self, mock_jwk, mock_chall):
        """ challenge check with with succ http challenge """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__value':
            'authorization__value',
            'type':
            'http-01',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        self.challenge.dbstore.jwk_load.return_value = 'pub_key'
        mock_chall.return_value = (True, 'foo')
        mock_jwk.return_value = 'jwk_thumbprint'
        self.assertEqual((True, 'foo'),
                         self.challenge._check('name', 'payload'))

    @patch('acme.challenge.Challenge._validate_dns_challenge')
    @patch('acme.challenge.jwk_thumbprint_get')
    def test_039_challenge__check(self, mock_jwk, mock_chall):
        """ challenge check with with failed dns challenge """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__value':
            'authorization__value',
            'type':
            'dns-01',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        self.challenge.dbstore.jwk_load.return_value = 'pub_key'
        mock_chall.return_value = (True, 'foo')
        mock_jwk.return_value = 'jwk_thumbprint'
        self.assertEqual((True, 'foo'),
                         self.challenge._check('name', 'payload'))

    @patch('acme.challenge.Challenge._validate_dns_challenge')
    @patch('acme.challenge.jwk_thumbprint_get')
    def test_040_challenge__check(self, mock_jwk, mock_chall):
        """ challenge check with with succ http challenge """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__value':
            'authorization__value',
            'type':
            'dns-01',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        self.challenge.dbstore.jwk_load.return_value = 'pub_key'
        mock_chall.return_value = (True, 'foo')
        mock_jwk.return_value = 'jwk_thumbprint'
        self.assertTrue((False, 'foo'),
                        self.challenge._check('name', 'payload'))

    @patch('acme.challenge.Challenge._validate_tkauth_challenge')
    @patch('acme.challenge.jwk_thumbprint_get')
    def test_041_challenge__check(self, mock_jwk, mock_chall):
        """ challenge check with with failed tkauth challenge tnauthlist_support not configured """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__value':
            'authorization__value',
            'type':
            'tkauth-01',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        self.challenge.dbstore.jwk_load.return_value = 'pub_key'
        mock_chall.return_value = (False, 'foo')
        mock_jwk.return_value = 'jwk_thumbprint'
        self.assertEqual((False, True),
                         self.challenge._check('name', 'payload'))

    @patch('acme.challenge.Challenge._validate_tkauth_challenge')
    @patch('acme.challenge.jwk_thumbprint_get')
    def test_042_challenge__check(self, mock_jwk, mock_chall):
        """ challenge check with with failed tkauth challenge tnauthlist_support True """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__value':
            'authorization__value',
            'type':
            'tkauth-01',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        self.challenge.dbstore.jwk_load.return_value = 'pub_key'
        self.challenge.tnauthlist_support = True
        mock_chall.return_value = (False, 'foo')
        mock_jwk.return_value = 'jwk_thumbprint'
        self.assertEqual((False, 'foo'),
                         self.challenge._check('name', 'payload'))

    @patch('acme.challenge.Challenge._validate_tkauth_challenge')
    @patch('acme.challenge.jwk_thumbprint_get')
    def test_043_challenge__check(self, mock_jwk, mock_chall):
        """ challenge check with with succ tkauth challenge and tnauthlist_support unset """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__value':
            'authorization__value',
            'type':
            'tkauth-01',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        self.challenge.dbstore.jwk_load.return_value = 'pub_key'
        self.challenge.tnauthlist_support = False
        mock_chall.return_value = (True, 'foo')
        mock_jwk.return_value = 'jwk_thumbprint'
        self.assertEqual((False, True),
                         self.challenge._check('name', 'payload'))

    @patch('acme.challenge.Challenge._validate_tkauth_challenge')
    @patch('acme.challenge.jwk_thumbprint_get')
    def test_044_challenge__check(self, mock_jwk, mock_chall):
        """ challenge check with with succ tkauth challenge and tnauthlist support set """
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__value':
            'authorization__value',
            'type':
            'tkauth-01',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        self.challenge.dbstore.jwk_load.return_value = 'pub_key'
        self.challenge.tnauthlist_support = True
        mock_chall.return_value = (True, 'foo')
        mock_jwk.return_value = 'jwk_thumbprint'
        self.assertEqual((True, 'foo'),
                         self.challenge._check('name', 'payload'))

    def test_045_challenge__wcd_manipulate(self):
        """ get fqdn wc manipulation """
        fqdn = 'foo.bar'
        self.assertEqual('foo.bar', self.challenge._wcd_manipulate(fqdn))

    def test_046_challenge__wcd_manipulate(self):
        """ get fqdn wc manipulation """
        fqdn = '*.foo.bar'
        self.assertEqual('foo.bar', self.challenge._wcd_manipulate(fqdn))

    def test_047_challenge__wcd_manipulate(self):
        """ get fqdn wc manipulation """
        fqdn = 'foo*.foo.bar'
        self.assertEqual('foo*.foo.bar', self.challenge._wcd_manipulate(fqdn))

    def test_048_challenge__challengelist_search(self):
        """ test Challenge._challengelist_search - dbstore.challenges_search() raises an exception  """
        self.challenge.dbstore.challenges_search.side_effect = Exception(
            'exc_chall_search')
        with self.assertLogs('test_a2c', level='INFO') as lcm:
            self.challenge._challengelist_search('key', 'value')
        self.assertIn(
            'CRITICAL:test_a2c:acme2certifier database error in Challenge._challengelist_search(): exc_chall_search',
            lcm.output)

    def test_049_challenge__check(self):
        """ test Challenge._check - dbstore.jwk_load() raises an exception  """
        self.challenge.dbstore.jwk_load.side_effect = Exception('exc_jkw_load')
        self.challenge.dbstore.challenge_lookup.return_value = {
            'type':
            'type',
            'authorization__value':
            'authorization__value',
            'token':
            'token',
            'authorization__order__account__name':
            'authorization__order__account__name'
        }
        with self.assertLogs('test_a2c', level='INFO') as lcm:
            self.challenge._check('name', 'payload')
        self.assertIn(
            'CRITICAL:test_a2c:acme2certifier database error in Challenge._check() jwk: exc_jkw_load',
            lcm.output)

    def test_050_challenge__check(self):
        """ test Challenge._check - dbstore.challenge_lookup() raises an exception  """
        self.challenge.dbstore.challenge_lookup.side_effect = Exception(
            'exc_chall_chk')
        with self.assertLogs('test_a2c', level='INFO') as lcm:
            self.challenge._check('name', 'payload')
        self.assertIn(
            'CRITICAL:test_a2c:acme2certifier database error in Challenge._check() lookup: exc_chall_chk',
            lcm.output)

    def test_051_challenge__info(self):
        """ test Challenge._info - dbstore.challenge_lookup() raises an exception  """
        self.challenge.dbstore.challenge_lookup.side_effect = Exception(
            'exc_chall_info')
        with self.assertLogs('test_a2c', level='INFO') as lcm:
            self.challenge._info('name')
        self.assertIn(
            'CRITICAL:test_a2c:acme2certifier database error in Challenge._info(): exc_chall_info',
            lcm.output)

    def test_052_challenge__new(self):
        """ test Challenge._new - dbstore.challenge_add() raises an exception  """
        self.challenge.dbstore.challenge_add.side_effect = Exception(
            'exc_chall_add')
        with self.assertLogs('test_a2c', level='INFO') as lcm:
            self.challenge._new('authz_name', 'mtype', 'token')
        self.assertIn(
            'CRITICAL:test_a2c:acme2certifier database error in Challenge._new(): exc_chall_add',
            lcm.output)

    def test_053_challenge__update(self):
        """ test Challenge._update - dbstore.challenge_update() raises an exception  """
        self.challenge.dbstore.challenge_update.side_effect = Exception(
            'exc_chall_upd')
        with self.assertLogs('test_a2c', level='INFO') as lcm:
            self.challenge._update({'foo': 'bar'})
        self.assertIn(
            'CRITICAL:test_a2c:acme2certifier database error in Challenge._update(): exc_chall_upd',
            lcm.output)

    def test_054_challenge__update_authz(self):
        """ test Challenge._update_authz - dbstore.authorization_update() raises an exception  """
        self.challenge.dbstore.authorization_update.side_effect = Exception(
            'exc_chall_autz_upd')
        self.challenge.dbstore.challenge_lookup.return_value = {
            'authorization__name': 'authorization__name',
            'authorization': 'authorization'
        }
        with self.assertLogs('test_a2c', level='INFO') as lcm:
            self.challenge._update_authz('name', {'foo': 'bar'})
        self.assertIn(
            'CRITICAL:test_a2c:acme2certifier database error in Challenge._update_authz() upd: exc_chall_autz_upd',
            lcm.output)

    def test_055_challenge__update_authz(self):
        """ test Challenge._update_authz - dbstore.authorization_update() raises an exception  """
        self.challenge.dbstore.challenge_lookup.side_effect = Exception(
            'exc_chall_lookup_foo')
        with self.assertLogs('test_a2c', level='INFO') as lcm:
            self.challenge._update_authz('name', {'foo': 'bar'})
        self.assertIn(
            'CRITICAL:test_a2c:acme2certifier database error in Challenge._update_authz() lookup: exc_chall_lookup_foo',
            lcm.output)

    @patch('acme.challenge.fqdn_resolve')
    def test_056_challenge__validate_alpn_challenge(self, mock_resolve):
        """ test validate_alpn_challenge fqdn_resolve returned Invalid """
        mock_resolve.return_value = (None, True)
        self.assertEqual(
            (False, True),
            self.challenge._validate_alpn_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))

    @patch('acme.challenge.servercert_get')
    @patch('acme.challenge.fqdn_resolve')
    def test_057_challenge__validate_alpn_challenge(self, mock_resolve,
                                                    mock_srv):
        """ test validate_alpn_challenge no certificate returned """
        mock_resolve.return_value = ('foo', False)
        mock_srv.return_value = None
        self.assertEqual(
            (False, False),
            self.challenge._validate_alpn_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))

    @patch('acme.challenge.fqdn_in_san_check')
    @patch('acme.challenge.cert_san_get')
    @patch('acme.challenge.servercert_get')
    @patch('acme.challenge.fqdn_resolve')
    def test_058_challenge__validate_alpn_challenge(self, mock_resolve,
                                                    mock_srv, mock_sanget,
                                                    mock_sanchk):
        """ test validate_alpn_challenge sancheck returned false """
        mock_resolve.return_value = ('foo', False)
        mock_sanget.return_value = ['foo', 'bar']
        mock_sanchk.return_value = False
        mock_srv.return_value = 'cert'
        self.assertEqual(
            (False, False),
            self.challenge._validate_alpn_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))

    @patch('acme.challenge.cert_extensions_get')
    @patch('acme.challenge.b64_encode')
    @patch('acme.challenge.fqdn_in_san_check')
    @patch('acme.challenge.cert_san_get')
    @patch('acme.challenge.servercert_get')
    @patch('acme.challenge.fqdn_resolve')
    def test_059_challenge__validate_alpn_challenge(self, mock_resolve,
                                                    mock_srv, mock_sanget,
                                                    mock_sanchk, mock_encode,
                                                    mock_ext):
        """ test validate_alpn_challenge extension check failed """
        mock_resolve.return_value = ('foo', False)
        mock_sanget.return_value = ['foo', 'bar']
        mock_sanchk.return_value = True
        mock_srv.return_value = 'cert'
        mock_encode.return_value = 'foo'
        mock_ext.return_value = ['foobar', 'bar', 'foo1']
        self.assertEqual(
            (False, False),
            self.challenge._validate_alpn_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))

    @patch('acme.challenge.cert_extensions_get')
    @patch('acme.challenge.b64_encode')
    @patch('acme.challenge.fqdn_in_san_check')
    @patch('acme.challenge.cert_san_get')
    @patch('acme.challenge.servercert_get')
    @patch('acme.challenge.fqdn_resolve')
    def test_060_challenge__validate_alpn_challenge(self, mock_resolve,
                                                    mock_srv, mock_sanget,
                                                    mock_sanchk, mock_encode,
                                                    mock_ext):
        """ test validate_alpn_challenge extension sucessful """
        mock_resolve.return_value = ('foo', False)
        mock_sanget.return_value = ['foo', 'bar']
        mock_sanchk.return_value = True
        mock_srv.return_value = 'cert'
        mock_encode.return_value = 'foo'
        mock_ext.return_value = ['foobar', 'bar', 'foo']
        self.assertEqual(
            (True, False),
            self.challenge._validate_alpn_challenge('cert_name', 'fqdn',
                                                    'token', 'jwk_thumbprint'))