cheroot icon indicating copy to clipboard operation
cheroot copied to clipboard

cheroot/test/test_ssl.py:326: TypeError: argument of type 'int' is not iterable

Open radez opened this issue 6 years ago • 7 comments

I'm submitting a ...

  • [X] 🐞 bug report
  • [ ] 🐣 feature request
  • [ ] ❓ question about the decisions made in the repository

🐞 Describe the bug. What is the current behavior? Getting a TypeError when running tests under Py3

What is the motivation / use case for changing the behavior?

💡 To Reproduce LANG=C.utf-8 /usr/bin/python3 -m pytest --ignore=build

💡 Expected behavior test passes

📋 Details

___ test_tls_client_auth[VerifyMode.CERT_REQUIRED-False-localhost-pyopenssl] ___

mocker = <pytest_mock.MockFixture object at 0x7f126e781a90>
tls_http_server = <generator object tls_http_server.<locals>.start_srv at 0x7f126e9c0a20>
adapter_type = 'pyopenssl', ca = <trustme.CA object at 0x7f126e781be0>
tls_certificate = <trustme.LeafCert object at 0x7f126cf17be0>
tls_certificate_chain_pem_path = '/tmp/tmp_1ydbkz8.pem'
tls_certificate_private_key_pem_path = '/tmp/tmppnq0li9y.pem'
tls_ca_certificate_pem_path = '/tmp/tmprtqcxjrb.pem', is_trusted_cert = False
tls_client_identity = 'localhost'
tls_verify_mode = <VerifyMode.CERT_REQUIRED: 2>

    @pytest.mark.parametrize(
        'adapter_type',
        (
            'builtin',
            'pyopenssl',
        ),
    )
    @pytest.mark.parametrize(
        'is_trusted_cert,tls_client_identity',
        (
            (True, 'localhost'), (True, '127.0.0.1'),
            (True, '*.localhost'), (True, 'not_localhost'),
            (False, 'localhost'),
        ),
    )
    @pytest.mark.parametrize(
        'tls_verify_mode',
        (
            ssl.CERT_NONE,  # server shouldn't validate client cert
            ssl.CERT_OPTIONAL,  # same as CERT_REQUIRED in client mode, don't use
            ssl.CERT_REQUIRED,  # server should validate if client cert CA is OK
        ),
    )
    def test_tls_client_auth(
        # FIXME: remove twisted logic, separate tests
        mocker,
        tls_http_server, adapter_type,
        ca,
        tls_certificate,
        tls_certificate_chain_pem_path,
        tls_certificate_private_key_pem_path,
        tls_ca_certificate_pem_path,
        is_trusted_cert, tls_client_identity,
        tls_verify_mode,
    ):
        """Verify that client TLS certificate auth works correctly."""
        test_cert_rejection = (
            tls_verify_mode != ssl.CERT_NONE
            and not is_trusted_cert
        )
        interface, _host, port = _get_conn_data(ANY_INTERFACE_IPV4)
    
        client_cert_root_ca = ca if is_trusted_cert else trustme.CA()
        with mocker.mock_module.patch(
            'idna.core.ulabel',
            return_value=ntob(tls_client_identity),
        ):
            client_cert = client_cert_root_ca.issue_server_cert(
                # FIXME: change to issue_cert once new trustme is out
                ntou(tls_client_identity),
            )
            del client_cert_root_ca
    
        with client_cert.private_key_and_cert_chain_pem.tempfile() as cl_pem:
            tls_adapter_cls = get_ssl_adapter_class(name=adapter_type)
            tls_adapter = tls_adapter_cls(
                tls_certificate_chain_pem_path,
                tls_certificate_private_key_pem_path,
            )
            if adapter_type == 'pyopenssl':
                tls_adapter.context = tls_adapter.get_context()
                tls_adapter.context.set_verify(
                    _stdlib_to_openssl_verify[tls_verify_mode],
                    lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
                )
            else:
                tls_adapter.context.verify_mode = tls_verify_mode
    
            ca.configure_trust(tls_adapter.context)
            tls_certificate.configure_cert(tls_adapter.context)
    
            tlshttpserver = tls_http_server.send(
                (
                    (interface, port),
                    tls_adapter,
                ),
            )
    
            interface, _host, port = _get_conn_data(tlshttpserver.bind_addr)
    
            make_https_request = functools.partial(
                requests.get,
                'https://' + interface + ':' + str(port) + '/',
    
                # Server TLS certificate verification:
                verify=tls_ca_certificate_pem_path,
    
                # Client TLS certificate verification:
                cert=cl_pem,
            )
    
            if not test_cert_rejection:
                resp = make_https_request()
                is_req_successful = resp.status_code == 200
                if (
                        not is_req_successful
                        and IS_PYOPENSSL_SSL_VERSION_1_0
                        and adapter_type == 'builtin'
                        and tls_verify_mode == ssl.CERT_REQUIRED
                        and tls_client_identity == 'localhost'
                        and is_trusted_cert
                ):
                    pytest.xfail(
                        'OpenSSL 1.0 has problems with verifying client certs',
                    )
                assert is_req_successful
                assert resp.text == 'Hello world!'
                return
    
            with pytest.raises(requests.exceptions.SSLError) as ssl_err:
                make_https_request()
    
            err_text = ssl_err.value.args[0].reason.args[0].args[0]
    
            expected_substring = (
                'sslv3 alert bad certificate' if IS_LIBRESSL_BACKEND
                else 'tlsv1 alert unknown ca'
            )
            if IS_PYPY and six.PY3 and IS_MACOS and adapter_type == 'pyopenssl':
                expected_substring = 'tlsv1 alert unknown ca'
>           assert expected_substring in err_text
E           TypeError: argument of type 'int' is not iterable

cheroot/test/test_ssl.py:326: TypeError

📋 Environment

  • Cheroot version: 6.5.4
  • Python version: 3.7.6
  • OS: Fedora 31

radez avatar Apr 30 '19 12:04 radez

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 29 '19 13:06 stale[bot]

Reran this on 6.5.6: maybe more of the error could help? I'm not sure how to debug this.

_host      = '127.0.0.1'
adapter_type = 'pyopenssl'
ca         = <trustme.CA object at 0x7f0a7b265250>
cl_pem     = '/tmp/tmp93eiln0c.pem'
client_cert = <trustme.LeafCert object at 0x7f0a79a3bb90>
err_text   = 1
expected_ssl_errors = (<class 'requests.exceptions.SSLError'>,)
expected_substrings = ('tlsv1 alert unknown ca',)
interface  = '127.0.0.1'
is_trusted_cert = False
make_https_request = functools.partial(<function get at 0x7f0a7c26fb00>, 'https://127.0.0.1:60843/', verify='/tmp/tmpt3k6ufop.pem', cert='/tmp/tmp93eiln0c.pem')
mocker     = <pytest_mock.MockFixture object at 0x7f0a7b265b50>
port       = 60843
ssl_err    = <ExceptionInfo SSLError tblen=6>
test_cert_rejection = True
tls_adapter = <cheroot.ssl.pyopenssl.pyOpenSSLAdapter object at 0x7f0a79a39390>
tls_adapter_cls = <class 'cheroot.ssl.pyopenssl.pyOpenSSLAdapter'>
tls_ca_certificate_pem_path = '/tmp/tmpt3k6ufop.pem'
tls_certificate = <trustme.LeafCert object at 0x7f0a799caf50>
tls_certificate_chain_pem_path = '/tmp/tmpede6i683.pem'
tls_certificate_private_key_pem_path = '/tmp/tmpwc6kdpox.pem'
tls_client_identity = 'localhost'
tls_http_server = <generator object tls_http_server.<locals>.start_srv at 0x7f0a7b25cb50>
tls_verify_mode = <VerifyMode.CERT_REQUIRED: 2>
tlshttpserver = <cheroot.server.HTTPServer object at 0x7f0a79a2add0>

cheroot/test/test_ssl.py:365: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

.0 = <tuple_iterator object at 0x7f0a79a3bb50>

>   assert any(e in err_text for e in expected_substrings)
E   TypeError: argument of type 'int' is not iterable

.0         = <tuple_iterator object at 0x7f0a79a3bb50>
e          = 'tlsv1 alert unknown ca'
err_text   = 1

cheroot/test/test_ssl.py:365: TypeError
------------------------------------------------------------------------------------------------------------ Captured stderr call ------------------------------------------------------------------------------------------------------------
Exception ignored in: <_io.FileIO name='/tmp/tmpede6i683.pem' mode='rb' closefd=True>
ResourceWarning: unclosed file <_io.BufferedReader name='/tmp/tmpede6i683.pem'>

radez avatar Aug 19 '19 19:08 radez

Hey @radez, could you please figure out what's in ssl_err in your case?

webknjaz avatar Aug 20 '19 21:08 webknjaz

Could you please prepare a Docker image with reproducer? I tried this under fedora:31 from dockerhub but I'm getting different errors. I need the exact same env in order to reproduce the problem.

webknjaz avatar Aug 20 '19 21:08 webknjaz

I've not used reproducer. I'll have to read some docs on it. Is ssl_err a log?

radez avatar Aug 21 '19 00:08 radez

I realized that ssl_err was one of the fields in the report: value is: ExceptionInfo SSLError tblen=6 It just had brackets around it so it probably got stripped out or something.

radez avatar Aug 21 '19 18:08 radez

@radez we need to figure out what nested attribute holds the error reason.

webknjaz avatar Aug 21 '19 20:08 webknjaz