Commit cb4ea281 authored by Vincent Pelletier's avatar Vincent Pelletier

all: Drop the need for install-time 2to3.

Preserve py2.7 compatibility.
Also, make pylint happier with the result.
parent 9466242b
...@@ -8,6 +8,8 @@ max-module-lines=1500 ...@@ -8,6 +8,8 @@ max-module-lines=1500
[MESSAGES CONTROL] [MESSAGES CONTROL]
disable= disable=
duplicate-code,
fixme,
invalid-name, invalid-name,
bad-continuation, bad-continuation,
bad-whitespace, bad-whitespace,
......
...@@ -174,7 +174,7 @@ class CertificateAuthority(object): ...@@ -174,7 +174,7 @@ class CertificateAuthority(object):
oid=_SUBJECT_OID_DICT[key], oid=_SUBJECT_OID_DICT[key],
value=value, value=value,
) )
for key, value in dict(ca_subject_dict).iteritems() for key, value in dict(ca_subject_dict).items()
]) ])
self._ca_extension_list = list(ca_extension_list) self._ca_extension_list = list(ca_extension_list)
if ca_life_period < 3: if ca_life_period < 3:
...@@ -680,7 +680,7 @@ class CertificateAuthority(object): ...@@ -680,7 +680,7 @@ class CertificateAuthority(object):
self.getCACertificateList(), self.getCACertificateList(),
crl_list=[ crl_list=[
x509.load_pem_x509_crl(x, _cryptography_backend) x509.load_pem_x509_crl(x, _cryptography_backend)
for x in self.getCertificateRevocationListDict().itervalues() for x in self.getCertificateRevocationListDict().values()
], ],
) )
self._storage.revoke( self._storage.revoke(
...@@ -732,7 +732,7 @@ class CertificateAuthority(object): ...@@ -732,7 +732,7 @@ class CertificateAuthority(object):
self.getCACertificateList(), self.getCACertificateList(),
crl_list=[ crl_list=[
x509.load_pem_x509_crl(x, _cryptography_backend) x509.load_pem_x509_crl(x, _cryptography_backend)
for x in self.getCertificateRevocationListDict().itervalues() for x in self.getCertificateRevocationListDict().values()
], ],
) )
return self._createCertificate( return self._createCertificate(
...@@ -852,7 +852,7 @@ class UserCertificateAuthority(CertificateAuthority): ...@@ -852,7 +852,7 @@ class UserCertificateAuthority(CertificateAuthority):
ca_cert_list = self.getCACertificateList() ca_cert_list = self.getCACertificateList()
crl_list = [ crl_list = [
x509.load_pem_x509_crl(x, _cryptography_backend) x509.load_pem_x509_crl(x, _cryptography_backend)
for x in self.getCertificateRevocationListDict().itervalues() for x in self.getCertificateRevocationListDict().values()
] ]
signing_key = os.urandom(32) signing_key = os.urandom(32)
symetric_key = os.urandom(32) symetric_key = os.urandom(32)
......
...@@ -25,7 +25,11 @@ from __future__ import absolute_import, print_function ...@@ -25,7 +25,11 @@ from __future__ import absolute_import, print_function
import argparse import argparse
from binascii import hexlify from binascii import hexlify
import datetime import datetime
import httplib try:
import http.client as http_client
except ImportError: # pragma: no cover
# BBB: py2.7
import httplib as http_client
import json import json
import os import os
import socket import socket
...@@ -42,6 +46,9 @@ from .client import ( ...@@ -42,6 +46,9 @@ from .client import (
HTTPSOnlyCaucaseClient, HTTPSOnlyCaucaseClient,
) )
if sys.version_info[0] >= 3: # pragma: no cover
unicode = str
class RetryingCaucaseClient(CaucaseClient): class RetryingCaucaseClient(CaucaseClient):
""" """
Similar to CaucaseClient, but retries indefinitely on http & socket errors. Similar to CaucaseClient, but retries indefinitely on http & socket errors.
...@@ -69,10 +76,10 @@ class RetryingCaucaseClient(CaucaseClient): ...@@ -69,10 +76,10 @@ class RetryingCaucaseClient(CaucaseClient):
# but so do errors which are either sign of code bugs # but so do errors which are either sign of code bugs
# (ImproperConnectionState) or sign of garbage values provided by # (ImproperConnectionState) or sign of garbage values provided by
# caller/user, and these should be let through. # caller/user, and these should be let through.
httplib.BadStatusLine, http_client.BadStatusLine,
httplib.LineTooLong, http_client.LineTooLong,
httplib.UnknownProtocol, http_client.UnknownProtocol,
httplib.IncompleteRead, http_client.IncompleteRead,
) as exception: ) as exception:
connection.close() # Resets HTTPConnection state machine. connection.close() # Resets HTTPConnection state machine.
# Note: repr(str(exception)) is nicer than repr(exception), without # Note: repr(str(exception)) is nicer than repr(exception), without
...@@ -156,12 +163,12 @@ class CLICaucaseClient(object): ...@@ -156,12 +163,12 @@ class CLICaucaseClient(object):
try: try:
crt_pem = self._client.getCertificate(crt_id) crt_pem = self._client.getCertificate(crt_id)
except CaucaseError as e: except CaucaseError as e:
if e.args[0] != httplib.NOT_FOUND: if e.args[0] != http_client.NOT_FOUND:
raise raise
try: try:
self._client.getCertificateSigningRequest(crt_id) self._client.getCertificateSigningRequest(crt_id)
except CaucaseError as e: except CaucaseError as e:
if e.args[0] != httplib.NOT_FOUND: if e.args[0] != http_client.NOT_FOUND:
raise raise
self._print(crt_id, 'not found - maybe CSR was rejected ?') self._print(crt_id, 'not found - maybe CSR was rejected ?')
error = True error = True
...@@ -707,8 +714,8 @@ def probe(argv=None): ...@@ -707,8 +714,8 @@ def probe(argv=None):
) )
ca_url, = parser.parse_args(argv).ca_url ca_url, = parser.parse_args(argv).ca_url
cas_url = ca_url + '/cas' cas_url = ca_url + '/cas'
with CaucaseClient(ca_url=cas_url) as http_client: with CaucaseClient(ca_url=cas_url) as caucase_client:
http_ca_pem = http_client.getCACertificate() http_ca_pem = caucase_client.getCACertificate()
with HTTPSOnlyCaucaseClient( with HTTPSOnlyCaucaseClient(
ca_url=cas_url, ca_url=cas_url,
ca_crt_pem_list=[http_ca_pem], ca_crt_pem_list=[http_ca_pem],
...@@ -716,7 +723,7 @@ def probe(argv=None): ...@@ -716,7 +723,7 @@ def probe(argv=None):
https_ca_pem = https_client.getCACertificate() https_ca_pem = https_client.getCACertificate()
# Retrieve again in case there was a renewal between both calls - we do # Retrieve again in case there was a renewal between both calls - we do
# not expect 2 renewals in very short succession. # not expect 2 renewals in very short succession.
http2_ca_pem = http_client.getCACertificate() http2_ca_pem = caucase_client.getCACertificate()
if https_ca_pem not in (http_ca_pem, http2_ca_pem): if https_ca_pem not in (http_ca_pem, http2_ca_pem):
raise ValueError('http and https do not serve the same caucase database') raise ValueError('http and https do not serve the same caucase database')
...@@ -878,7 +885,7 @@ def updater(argv=None, until=utils.until): ...@@ -878,7 +885,7 @@ def updater(argv=None, until=utils.until):
try: try:
crt_pem = client.getCertificate(csr_id) crt_pem = client.getCertificate(csr_id)
except CaucaseError as e: except CaucaseError as e:
if e.args[0] != httplib.NOT_FOUND: if e.args[0] != http_client.NOT_FOUND:
raise raise
# If server does not know our CSR anymore, getCSR will raise. # If server does not know our CSR anymore, getCSR will raise.
# If it does, we were likely rejected, so exit by letting exception # If it does, we were likely rejected, so exit by letting exception
......
...@@ -22,10 +22,16 @@ ...@@ -22,10 +22,16 @@
Caucase - Certificate Authority for Users, Certificate Authority for SErvices Caucase - Certificate Authority for Users, Certificate Authority for SErvices
""" """
from __future__ import absolute_import from __future__ import absolute_import
import httplib try:
import http.client as http_client
except ImportError: # BBB: py2.7
import httplib as http_client
import json import json
import ssl import ssl
from urlparse import urlparse try:
from urllib.parse import urlparse
except ImportError: # BBB: py2.7
from urlparse import urlparse
from cryptography import x509 from cryptography import x509
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
import cryptography.exceptions import cryptography.exceptions
...@@ -68,8 +74,8 @@ class CaucaseClient(object): ...@@ -68,8 +74,8 @@ class CaucaseClient(object):
Expose caucase REST API as pythonic methods. Expose caucase REST API as pythonic methods.
""" """
HTTPConnection = httplib.HTTPConnection HTTPConnection = http_client.HTTPConnection
HTTPSConnection = httplib.HTTPSConnection HTTPSConnection = http_client.HTTPSConnection
@classmethod @classmethod
def updateCAFile(cls, url, ca_crt_path): def updateCAFile(cls, url, ca_crt_path):
...@@ -153,7 +159,7 @@ class CaucaseClient(object): ...@@ -153,7 +159,7 @@ class CaucaseClient(object):
server_crl_list = client.getCertificateRevocationListList() server_crl_list = client.getCertificateRevocationListList()
for ca_key_id, crl_pem in _asCRLDict( for ca_key_id, crl_pem in _asCRLDict(
crl_pem_list=server_crl_list, crl_pem_list=server_crl_list,
).iteritems(): ).items():
updated |= local_crl_dict.pop(ca_key_id, None) != crl_pem updated |= local_crl_dict.pop(ca_key_id, None) != crl_pem
updated |= bool(local_crl_dict) updated |= bool(local_crl_dict)
if updated: if updated:
......
...@@ -33,12 +33,18 @@ import itertools ...@@ -33,12 +33,18 @@ import itertools
import json import json
import os import os
import socket import socket
from SocketServer import ThreadingMixIn try:
from socketserver import ThreadingMixIn
except ImportError: # BBB: py2.7
from SocketServer import ThreadingMixIn
import ssl import ssl
import sys import sys
import tempfile import tempfile
from threading import Thread from threading import Thread
from urlparse import urlparse, urlunsplit try:
from urllib.parse import urlparse, urlunsplit
except ImportError: # BBB: py2.7
from urlparse import urlparse, urlunsplit
from wsgiref.simple_server import make_server, WSGIServer from wsgiref.simple_server import make_server, WSGIServer
import ipaddress import ipaddress
from cryptography import x509 from cryptography import x509
...@@ -120,7 +126,7 @@ class ThreadingWSGIServer(ThreadingMixIn, WSGIServer): ...@@ -120,7 +126,7 @@ class ThreadingWSGIServer(ThreadingMixIn, WSGIServer):
- intercept EBADF on shutdown if select is interrupted: - intercept EBADF on shutdown if select is interrupted:
""" """
try: try:
return WSGIServer.serve_forever(self, *args, **kw) WSGIServer.serve_forever(self, *args, **kw)
except socket.error as exception: # pragma: no cover except socket.error as exception: # pragma: no cover
# Workaround for the following unhandled error: # Workaround for the following unhandled error:
# Traceback (most recent call last): # Traceback (most recent call last):
...@@ -147,7 +153,7 @@ class ThreadingWSGIServer(ThreadingMixIn, WSGIServer): ...@@ -147,7 +153,7 @@ class ThreadingWSGIServer(ThreadingMixIn, WSGIServer):
def _buildQuoteCharList(): def _buildQuoteCharList():
# All chars considered guilty # All chars considered guilty
result = ['\\x%02x' % x for x in xrange(256)] result = ['\\x%02x' % x for x in range(256)]
# Exception for non-printable whitespaces. # Exception for non-printable whitespaces.
result[ord('\b')] = '\\b' result[ord('\b')] = '\\b'
result[ord('\n')] = '\\n' result[ord('\n')] = '\\n'
...@@ -155,7 +161,7 @@ def _buildQuoteCharList(): ...@@ -155,7 +161,7 @@ def _buildQuoteCharList():
result[ord('\t')] = '\\t' result[ord('\t')] = '\\t'
result[ord('\v')] = '\\v' result[ord('\v')] = '\\v'
# Exception for printable chars # Exception for printable chars
for x in xrange(0x20, 0x7f): for x in range(0x20, 0x7f):
result[x] = chr(x) result[x] = chr(x)
# Exception in the exception: chars which need escapement # Exception in the exception: chars which need escapement
result[ord('\\')] = '\\\\' result[ord('\\')] = '\\\\'
...@@ -1056,7 +1062,7 @@ def manage(argv=None, stdout=sys.stdout): ...@@ -1056,7 +1062,7 @@ def manage(argv=None, stdout=sys.stdout):
db_path, db_path,
table_prefix='cas', table_prefix='cas',
) )
for identifier, ca_pair in import_ca_dict.iteritems(): for identifier, ca_pair in import_ca_dict.items():
found_from = ', '.join(ca_pair['from']) found_from = ', '.join(ca_pair['from'])
crt = ca_pair['crt'] crt = ca_pair['crt']
if crt is None: if crt is None:
......
...@@ -25,7 +25,11 @@ Test suite ...@@ -25,7 +25,11 @@ Test suite
""" """
# pylint: disable=too-many-lines, too-many-public-methods # pylint: disable=too-many-lines, too-many-public-methods
from __future__ import absolute_import from __future__ import absolute_import
from Cookie import SimpleCookie try:
from http.cookies import SimpleCookie
except ImportError: # pragma: no cover
# BBB: py2.7
from Cookie import SimpleCookie
import datetime import datetime
# pylint: disable=no-name-in-module, import-error # pylint: disable=no-name-in-module, import-error
from distutils.spawn import find_executable from distutils.spawn import find_executable
...@@ -33,8 +37,13 @@ from distutils.spawn import find_executable ...@@ -33,8 +37,13 @@ from distutils.spawn import find_executable
import errno import errno
import functools import functools
import glob import glob
import HTMLParser try: # pragma: no cover
import httplib import html.parser as html_parser
import http.client as http_client
except ImportError: # pragma: no cover
# BBB: py2.7
import HTMLParser as html_parser
import httplib as http_client
from io import BytesIO, StringIO from io import BytesIO, StringIO
import ipaddress import ipaddress
import json import json
...@@ -52,8 +61,13 @@ import tempfile ...@@ -52,8 +61,13 @@ import tempfile
import threading import threading
import time import time
import unittest import unittest
from urllib import quote, urlencode try: # pragma: no cover
import urlparse from urllib.parse import quote, urlencode
import urllib.parse as urllib_parse
except ImportError: # pragma: no cover
# BBB: py2.7
from urllib import quote, urlencode
import urlparse as urllib_parse
from cryptography import x509 from cryptography import x509
import cryptography.exceptions import cryptography.exceptions
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
...@@ -76,14 +90,26 @@ _cryptography_backend = default_backend() ...@@ -76,14 +90,26 @@ _cryptography_backend = default_backend()
NOT_CAUCASE_OID = '2.25.285541874270823339875695650038637483518' NOT_CAUCASE_OID = '2.25.285541874270823339875695650038637483518'
A_YEAR_IN_SECONDS = 60 * 60 * 24 * 365 # Roughly a year A_YEAR_IN_SECONDS = 60 * 60 * 24 * 365 # Roughly a year
class assertHTMLNoScriptAlert(HTMLParser.HTMLParser): if sys.version_info[0] >= 3: # pragma: no cover
TestCase = unittest.TestCase
else: # pragma: no cover
# BBB: py2.7
class TestCase(unittest.TestCase):
"""
For forward-compatibility wit 3.x unittest API.
"""
assertRegex = unittest.TestCase.assertRegexpMatches
class assertHTMLNoScriptAlert(
html_parser.HTMLParser,
): # pylint: disable=abstract-method
""" """
Raise AssertionError if it finds a <script> tag containing "alert". Raise AssertionError if it finds a <script> tag containing "alert".
""" """
_in_script = False _in_script = False
def __init__(self, data): def __init__(self, data):
HTMLParser.HTMLParser.__init__(self) html_parser.HTMLParser.__init__(self)
self.feed(data) self.feed(data)
self.close() self.close()
...@@ -91,7 +117,7 @@ class assertHTMLNoScriptAlert(HTMLParser.HTMLParser): ...@@ -91,7 +117,7 @@ class assertHTMLNoScriptAlert(HTMLParser.HTMLParser):
""" """
Out of script tag. Out of script tag.
""" """
HTMLParser.HTMLParser.reset(self) html_parser.HTMLParser.reset(self)
self._in_script = False self._in_script = False
def handle_starttag(self, tag, attrs): def handle_starttag(self, tag, attrs):
...@@ -138,7 +164,7 @@ def retry(callback, try_count=10, try_delay=0.1): # pragma: no cover ...@@ -138,7 +164,7 @@ def retry(callback, try_count=10, try_delay=0.1): # pragma: no cover
a true value. a true value.
Always returns the value returned by latest callback invocation. Always returns the value returned by latest callback invocation.
""" """
for _ in xrange(try_count): for _ in range(try_count):
result = callback() result = callback()
if result: if result:
break break
...@@ -320,7 +346,7 @@ def print_buffer_on_error(func): ...@@ -320,7 +346,7 @@ def print_buffer_on_error(func):
return wrapper return wrapper
_clean_caucased_snapshot = None _clean_caucased_snapshot = None
class CaucaseTest(unittest.TestCase): class CaucaseTest(TestCase):
""" """
Test a complete caucase setup: spawn a caucase-http server on CAUCASE_NETLOC Test a complete caucase setup: spawn a caucase-http server on CAUCASE_NETLOC
and use caucase-cli to access it. and use caucase-cli to access it.
...@@ -361,7 +387,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -361,7 +387,7 @@ class CaucaseTest(unittest.TestCase):
'localhost:8000', 'localhost:8000',
) )
self._caucase_url = 'http://' + netloc self._caucase_url = 'http://' + netloc
parsed_url = urlparse.urlparse(self._caucase_url) parsed_url = urllib_parse.urlparse(self._caucase_url)
self.assertFalse( self.assertFalse(
canConnect((parsed_url.hostname, parsed_url.port)), canConnect((parsed_url.hostname, parsed_url.port)),
'Something else is already listening on %r, define CAUCASE_NETLOC ' 'Something else is already listening on %r, define CAUCASE_NETLOC '
...@@ -641,7 +667,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -641,7 +667,7 @@ class CaucaseTest(unittest.TestCase):
) )
server.daemon = True server.daemon = True
server.start() server.start()
parsed_url = urlparse.urlparse(self._caucase_url) parsed_url = urllib_parse.urlparse(self._caucase_url)
if not retry( if not retry(
lambda: ( lambda: (
self.assertTrue(server.is_alive(), 'caucased crashed on startup') or self.assertTrue(server.is_alive(), 'caucased crashed on startup') or
...@@ -1241,7 +1267,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -1241,7 +1267,7 @@ class CaucaseTest(unittest.TestCase):
x509.CRLDistributionPoints, x509.CRLDistributionPoints,
).value ).value
crl_uri, = distribution_point.full_name crl_uri, = distribution_point.full_name
self.assertRegexpMatches( self.assertRegex(
crl_uri.value, crl_uri.value,
u'/cas/crl/%i$' % (ca_key_identifier, ), u'/cas/crl/%i$' % (ca_key_identifier, ),
) )
...@@ -1278,7 +1304,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -1278,7 +1304,7 @@ class CaucaseTest(unittest.TestCase):
Check that caucased accepts <count> CSR, and rejects the next one. Check that caucased accepts <count> CSR, and rejects the next one.
Appends the data of created CSRs (csr_id and csr_path) to csr_list. Appends the data of created CSRs (csr_id and csr_path) to csr_list.
""" """
for _ in xrange(count): for _ in range(count):
basename = self._getBaseName() basename = self._getBaseName()
csr_path = self._createBasicCSR( csr_path = self._createBasicCSR(
basename, basename,
...@@ -1801,7 +1827,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -1801,7 +1827,7 @@ class CaucaseTest(unittest.TestCase):
for ( for (
authority_key_identifier, authority_key_identifier,
(crl_pem, _), (crl_pem, _),
) in crl_pem_dict.items(): ) in list(crl_pem_dict.items()):
crl_pem_dict[authority_key_identifier] = ( crl_pem_dict[authority_key_identifier] = (
crl_pem, crl_pem,
datetime.datetime.utcnow() - datetime.timedelta(0, 1), datetime.datetime.utcnow() - datetime.timedelta(0, 1),
...@@ -1813,7 +1839,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -1813,7 +1839,7 @@ class CaucaseTest(unittest.TestCase):
for ( for (
authority_key_identifier, authority_key_identifier,
reference_crl_pem, reference_crl_pem,
) in reference_crl_pem_dict.iteritems(): ) in reference_crl_pem_dict.items():
self.assertEqual( self.assertEqual(
utils.load_crl( utils.load_crl(
new_crl_pem_dict[authority_key_identifier], new_crl_pem_dict[authority_key_identifier],
...@@ -2174,7 +2200,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -2174,7 +2200,7 @@ class CaucaseTest(unittest.TestCase):
self.assertEqual(header_dict.get('Content-Type'), 'application/pkix-crl') self.assertEqual(header_dict.get('Content-Type'), 'application/pkix-crl')
self.assertEqual(body, '\n'.join( self.assertEqual(body, '\n'.join(
x.decode('ascii') x.decode('ascii')
for x in cau_crl_dict.itervalues() for x in cau_crl_dict.values()
).encode('utf-8')) ).encode('utf-8'))
min_date = int(time.time()) min_date = int(time.time())
...@@ -2697,7 +2723,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -2697,7 +2723,7 @@ class CaucaseTest(unittest.TestCase):
), ),
) )
except SystemExit as e: # pragma: no cover except SystemExit as e: # pragma: no cover
if e.code: if e.code: # pylint: disable=using-constant-test
raise raise
after_restore = list(SQLite3Storage( after_restore = list(SQLite3Storage(
...@@ -2811,7 +2837,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -2811,7 +2837,7 @@ class CaucaseTest(unittest.TestCase):
c.execute('CREATE TABLE bloat (bloat TEXT)') c.execute('CREATE TABLE bloat (bloat TEXT)')
bloat_query = 'INSERT INTO bloat VALUES (?)' bloat_query = 'INSERT INTO bloat VALUES (?)'
bloat_value = ('bloat' * 10240, ) bloat_value = ('bloat' * 10240, )
for _ in xrange(1024): for _ in range(1024):
c.execute(bloat_query, bloat_value) c.execute(bloat_query, bloat_value)
db.close() db.close()
del db del db
...@@ -3171,10 +3197,10 @@ class CaucaseTest(unittest.TestCase): ...@@ -3171,10 +3197,10 @@ class CaucaseTest(unittest.TestCase):
for index, (HTTPConnection_method_id, injector) in enumerate(( for index, (HTTPConnection_method_id, injector) in enumerate((
('connect', injector), # Primed above ('connect', injector), # Primed above
('connect', ErrorInjector(socket.error(111, 'Connection refused'))), ('connect', ErrorInjector(socket.error(111, 'Connection refused'))),
('getresponse', ErrorInjector(httplib.BadStatusLine('blah'))), ('getresponse', ErrorInjector(http_client.BadStatusLine('blah'))),
('getresponse', ErrorInjector(httplib.LineTooLong('header line'))), ('getresponse', ErrorInjector(http_client.LineTooLong('header line'))),
('getresponse', ErrorInjector(httplib.UnknownProtocol('HTTP/pigeon'))), ('getresponse', ErrorInjector(http_client.UnknownProtocol('HTTP/pigeon'))),
('getresponse', ErrorInjector(httplib.IncompleteRead('you are my '))), ('getresponse', ErrorInjector(http_client.IncompleteRead('you are my '))),
)): )):
if index: if index:
# Set next fault # Set next fault
...@@ -3331,7 +3357,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -3331,7 +3357,7 @@ class CaucaseTest(unittest.TestCase):
# http server is started without backups by default, so deadline is ssl # http server is started without backups by default, so deadline is ssl
# renewal deadline. So fake expiration and verify the certificate presented # renewal deadline. So fake expiration and verify the certificate presented
# by https server changed. # by https server changed.
parsed_url = urlparse.urlparse(self._caucase_url) parsed_url = urllib_parse.urlparse(self._caucase_url)
# Sanity check # Sanity check
assert parsed_url.scheme == 'http', parsed_url.scheme assert parsed_url.scheme == 'http', parsed_url.scheme
address = ( address = (
...@@ -3360,7 +3386,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -3360,7 +3386,7 @@ class CaucaseTest(unittest.TestCase):
self._stopServer() self._stopServer()
os.unlink(self._server_key) os.unlink(self._server_key)
os.unlink(self._server_db) os.unlink(self._server_db)
port = urlparse.urlparse(self._caucase_url).port port = urllib_parse.urlparse(self._caucase_url).port
if port: # pragma: no cover if port: # pragma: no cover
netloc += ':%s' % port netloc += ':%s' % port
self._server_netloc = netloc self._server_netloc = netloc
...@@ -3382,7 +3408,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -3382,7 +3408,7 @@ class CaucaseTest(unittest.TestCase):
x509.CRLDistributionPoints, x509.CRLDistributionPoints,
).value ).value
uri, = distribution_point.full_name uri, = distribution_point.full_name
self.assertRegexpMatches( self.assertRegex(
uri.value, uri.value,
u'^' + re.escape(self._caucase_url) + u'/cas/crl/[0-9]+$', u'^' + re.escape(self._caucase_url) + u'/cas/crl/[0-9]+$',
) )
...@@ -3695,7 +3721,7 @@ class CaucaseTest(unittest.TestCase): ...@@ -3695,7 +3721,7 @@ class CaucaseTest(unittest.TestCase):
], ],
) )
for property_id, property_value in CaucaseTest.__dict__.iteritems(): for property_id, property_value in CaucaseTest.__dict__.items():
if property_id.startswith('test') and callable(property_value): if property_id.startswith('test') and callable(property_value):
setattr(CaucaseTest, property_id, print_buffer_on_error(property_value)) setattr(CaucaseTest, property_id, print_buffer_on_error(property_value))
...@@ -3735,7 +3761,7 @@ def _runCaucaseSh(*args): ...@@ -3735,7 +3761,7 @@ def _runCaucaseSh(*args):
_caucase_sh_path is None or _runCaucaseSh('--help')[0], _caucase_sh_path is None or _runCaucaseSh('--help')[0],
'caucase.sh not found or missing dependency', 'caucase.sh not found or missing dependency',
) )
class CaucaseShellTest(unittest.TestCase): class CaucaseShellTest(TestCase):
""" """
Test caucase.sh . Test caucase.sh .
""" """
......
...@@ -48,6 +48,24 @@ from .exceptions import ( ...@@ -48,6 +48,24 @@ from .exceptions import (
NotJSON, NotJSON,
) )
if sys.version_info[0] >= 3: # pragma: no cover
unicode = str
def getAuthorityKeyIdentifier(cert):
"""
Returns the authority key identifier of given certificate.
"""
# pylint: disable=no-member
return int.from_bytes(_getAuthorityKeyIdentifier(cert), 'big')
# pylint: enable=no-member
else: # pragma: no cover
# BBB: py2.7
def getAuthorityKeyIdentifier(cert):
"""
Returns the authority key identifier of given certificate.
"""
return int(_getAuthorityKeyIdentifier(cert).encode('hex'), 16)
DEFAULT_DIGEST_LIST = ('sha256', 'sha384', 'sha512') DEFAULT_DIGEST_LIST = ('sha256', 'sha384', 'sha512')
DEFAULT_DIGEST = DEFAULT_DIGEST_LIST[0] DEFAULT_DIGEST = DEFAULT_DIGEST_LIST[0]
DEFAULT_DIGEST_CLASS = getattr(hashes, DEFAULT_DIGEST.upper()) DEFAULT_DIGEST_CLASS = getattr(hashes, DEFAULT_DIGEST.upper())
...@@ -225,7 +243,7 @@ def _savePEMListToDirectory(dir_path, pem_list, pem_loader, extension): ...@@ -225,7 +243,7 @@ def _savePEMListToDirectory(dir_path, pem_list, pem_loader, extension):
if not os.path.islink(filepath) and filename in pem_dict: if not os.path.islink(filepath) and filename in pem_dict:
try: try:
# pylint: disable=unbalanced-tuple-unpacking # pylint: disable=unbalanced-tuple-unpacking
file_pem_item, = _getPEMTypeDict(filepath).itervalues() file_pem_item, = _getPEMTypeDict(filepath).values()
# pylint: enable=unbalanced-tuple-unpacking # pylint: enable=unbalanced-tuple-unpacking
# pylint: disable=broad-except # pylint: disable=broad-except
except Exception: except Exception:
...@@ -239,7 +257,7 @@ def _savePEMListToDirectory(dir_path, pem_list, pem_loader, extension): ...@@ -239,7 +257,7 @@ def _savePEMListToDirectory(dir_path, pem_list, pem_loader, extension):
else: else:
# Unknown file (ex: expired certificate), or a symlink to a file: delete # Unknown file (ex: expired certificate), or a symlink to a file: delete
os.unlink(filepath) os.unlink(filepath)
for filename, pem_item in pem_dict.iteritems(): for filename, pem_item in pem_dict.items():
filepath = os.path.join(dir_path, filename) filepath = os.path.join(dir_path, filename)
with open(filepath, 'wb') as pem_file: with open(filepath, 'wb') as pem_file:
pem_file.write(pem_item) pem_file.write(pem_item)
...@@ -578,21 +596,6 @@ def _getAuthorityKeyIdentifier(cert): ...@@ -578,21 +596,6 @@ def _getAuthorityKeyIdentifier(cert):
x509.AuthorityKeyIdentifier, x509.AuthorityKeyIdentifier,
).value.key_identifier ).value.key_identifier
if sys.version_info < (3, ): # pragma: no cover
def getAuthorityKeyIdentifier(cert):
"""
Returns the authority key identifier of given certificate.
"""
return int(_getAuthorityKeyIdentifier(cert).encode('hex'), 16)
else: # pragma: no cover
def getAuthorityKeyIdentifier(cert):
"""
Returns the authority key identifier of given certificate.
"""
# pylint: disable=no-member
return int.from_bytes(_getAuthorityKeyIdentifier(cert), 'big')
# pylint: enable=no-member
EPOCH = datetime.datetime(1970, 1, 1) EPOCH = datetime.datetime(1970, 1, 1)
def datetime2timestamp(value): def datetime2timestamp(value):
""" """
......
...@@ -22,24 +22,35 @@ ...@@ -22,24 +22,35 @@
Caucase - Certificate Authority for Users, Certificate Authority for SErvices Caucase - Certificate Authority for Users, Certificate Authority for SErvices
""" """
from __future__ import absolute_import from __future__ import absolute_import
from Cookie import SimpleCookie, CookieError try: # pragma: no cover
import httplib from http.cookies import SimpleCookie, CookieError
import http.client as http_client
except ImportError: # pragma: no cover
# BBB: py2.7
from Cookie import SimpleCookie, CookieError
import httplib as http_client
import json import json
import os import os
import sys import sys
import threading import threading
import time import time
from urllib import quote, urlencode try: # pragma: no cover
from urlparse import parse_qs from urllib.parse import quote, urlencode
from urllib.parse import parse_qs
except ImportError: # pragma: no cover
# BBB: py2.7
from urllib import quote, urlencode
from urlparse import parse_qs
from wsgiref.util import application_uri, request_uri from wsgiref.util import application_uri, request_uri
import jwt import jwt
from . import utils from . import utils
from . import exceptions from . import exceptions
# pylint: disable=import-error,no-name-in-module # pylint: disable=import-error,no-name-in-module
if sys.version_info >= (3, ): # pragma: no cover if sys.version_info[0] >= 3: # pragma: no cover
from html import escape from html import escape
else: # pragma: no cover else: # pragma: no cover
# BBB: py2.7
from cgi import escape from cgi import escape
# pylint: enable=import-error,no-name-in-module # pylint: enable=import-error,no-name-in-module
...@@ -83,13 +94,13 @@ CORS_COOKIE_ORIGIN_KEY = 'o' # Prevent an origin from stealing another's token. ...@@ -83,13 +94,13 @@ CORS_COOKIE_ORIGIN_KEY = 'o' # Prevent an origin from stealing another's token.
A_YEAR_IN_SECONDS = 60 * 60 * 24 * 365 # Roughly a year A_YEAR_IN_SECONDS = 60 * 60 * 24 * 365 # Roughly a year
def _getStatus(code): def _getStatus(code):
return '%i %s' % (code, httplib.responses[code]) return '%i %s' % (code, http_client.responses[code])
class ApplicationError(Exception): class ApplicationError(Exception):
""" """
WSGI HTTP error base class. WSGI HTTP error base class.
""" """
status = _getStatus(httplib.INTERNAL_SERVER_ERROR) status = _getStatus(http_client.INTERNAL_SERVER_ERROR)
_response_headers = [] _response_headers = []
@property @property
...@@ -103,13 +114,13 @@ class BadRequest(ApplicationError): ...@@ -103,13 +114,13 @@ class BadRequest(ApplicationError):
""" """
HTTP bad request error HTTP bad request error
""" """
status = _getStatus(httplib.BAD_REQUEST) status = _getStatus(http_client.BAD_REQUEST)
class Unauthorized(ApplicationError): class Unauthorized(ApplicationError):
""" """
HTTP unauthorized error HTTP unauthorized error
""" """
status = _getStatus(httplib.UNAUTHORIZED) status = _getStatus(http_client.UNAUTHORIZED)
class SSLUnauthorized(Unauthorized): class SSLUnauthorized(Unauthorized):
""" """
...@@ -136,19 +147,19 @@ class Forbidden(ApplicationError): ...@@ -136,19 +147,19 @@ class Forbidden(ApplicationError):
""" """
HTTP forbidden error HTTP forbidden error
""" """
status = _getStatus(httplib.FORBIDDEN) status = _getStatus(http_client.FORBIDDEN)
class NotFound(ApplicationError): class NotFound(ApplicationError):
""" """
HTTP not found error HTTP not found error
""" """
status = _getStatus(httplib.NOT_FOUND) status = _getStatus(http_client.NOT_FOUND)
class BadMethod(ApplicationError): class BadMethod(ApplicationError):
""" """
HTTP bad method error HTTP bad method error
""" """
status = _getStatus(httplib.METHOD_NOT_ALLOWED) status = _getStatus(http_client.METHOD_NOT_ALLOWED)
def __init__(self, allowed_list): def __init__(self, allowed_list):
super(BadMethod, self).__init__(allowed_list) super(BadMethod, self).__init__(allowed_list)
...@@ -160,13 +171,13 @@ class Conflict(ApplicationError): ...@@ -160,13 +171,13 @@ class Conflict(ApplicationError):
""" """
HTTP conflict HTTP conflict
""" """
status = _getStatus(httplib.CONFLICT) status = _getStatus(http_client.CONFLICT)
class TooLarge(ApplicationError): class TooLarge(ApplicationError):
""" """
HTTP too large error HTTP too large error
""" """
status = _getStatus(httplib.REQUEST_ENTITY_TOO_LARGE) status = _getStatus(http_client.REQUEST_ENTITY_TOO_LARGE)
class InsufficientStorage(ApplicationError): class InsufficientStorage(ApplicationError):
""" """
...@@ -175,18 +186,18 @@ class InsufficientStorage(ApplicationError): ...@@ -175,18 +186,18 @@ class InsufficientStorage(ApplicationError):
# python2.7's httplib lacks the textual description for 507, although it # python2.7's httplib lacks the textual description for 507, although it
# has the constant. # has the constant.
# And modern pylint on python3 complain that # And modern pylint on python3 complain that
# http.client.INSUFFICIENT_STORAGE, an enum item, is not suitable for %i # http_client.INSUFFICIENT_STORAGE, an enum item, is not suitable for %i
# (spoiler: it is suitable). # (spoiler: it is suitable).
# Also, older pylint (last version suppoting 2.7 ?) does not support # Also, older pylint (last version suppoting 2.7 ?) does not support
# bad-string-format-type but does not detect anything wrong here. # bad-string-format-type but does not detect anything wrong here.
# pylint: disable=bad-string-format-type # pylint: disable=bad-string-format-type
status = '%i Insufficient Storage' % (httplib.INSUFFICIENT_STORAGE, ) status = '%i Insufficient Storage' % (http_client.INSUFFICIENT_STORAGE, )
# pylint: enable=bad-string-format-type # pylint: enable=bad-string-format-type
STATUS_OK = _getStatus(httplib.OK) STATUS_OK = _getStatus(http_client.OK)
STATUS_CREATED = _getStatus(httplib.CREATED) STATUS_CREATED = _getStatus(http_client.CREATED)
STATUS_NO_CONTENT = _getStatus(httplib.NO_CONTENT) STATUS_NO_CONTENT = _getStatus(http_client.NO_CONTENT)
STATUS_FOUND = _getStatus(httplib.FOUND) STATUS_FOUND = _getStatus(http_client.FOUND)
MAX_BODY_LENGTH = 10 * 1024 * 1024 # 10 MB MAX_BODY_LENGTH = 10 * 1024 * 1024 # 10 MB
class CORSTokenManager(object): class CORSTokenManager(object):
...@@ -571,7 +582,7 @@ class Application(object): ...@@ -571,7 +582,7 @@ class Application(object):
# CORS headers added, add more # CORS headers added, add more
self._optionAddCORSHeaders(method_dict, cors_header_list) self._optionAddCORSHeaders(method_dict, cors_header_list)
else: else:
raise BadMethod(method_dict.keys() + ['OPTIONS']) raise BadMethod(list(method_dict.keys()) + ['OPTIONS'])
else: else:
subpath = action_dict.get('subpath', SUBPATH_FORBIDDEN) subpath = action_dict.get('subpath', SUBPATH_FORBIDDEN)
if ( if (
...@@ -680,7 +691,7 @@ class Application(object): ...@@ -680,7 +691,7 @@ class Application(object):
trusted_cert_list=ca_list, trusted_cert_list=ca_list,
crl_list=[ crl_list=[
utils.load_crl(x, ca_list) utils.load_crl(x, ca_list)
for x in self._cau.getCertificateRevocationListDict().itervalues() for x in self._cau.getCertificateRevocationListDict().values()
], ],
) )
except (exceptions.CertificateVerificationError, ValueError): except (exceptions.CertificateVerificationError, ValueError):
...@@ -731,7 +742,7 @@ class Application(object): ...@@ -731,7 +742,7 @@ class Application(object):
', '.join( ', '.join(
[ [
x x
for x, y in method_dict.iteritems() for x, y in method_dict.items()
if y.get('cors') is not CORS_POLICY_ALWAYS_DENY if y.get('cors') is not CORS_POLICY_ALWAYS_DENY
] + ['OPTIONS'], ] + ['OPTIONS'],
), ),
...@@ -868,14 +879,14 @@ class Application(object): ...@@ -868,14 +879,14 @@ class Application(object):
)] )]
while routing_dict_list: while routing_dict_list:
routing_path, routing_dict = routing_dict_list.pop() routing_path, routing_dict = routing_dict_list.pop()
for component, path_entry_dict in routing_dict.iteritems(): for component, path_entry_dict in routing_dict.items():
component_path = routing_path + '/' + component component_path = routing_path + '/' + component
if recurse and 'routing' in path_entry_dict: if recurse and 'routing' in path_entry_dict:
routing_dict_list.append(( routing_dict_list.append((
component_path, component_path,
path_entry_dict['routing'], path_entry_dict['routing'],
)) ))
for method, action_dict in path_entry_dict['method'].iteritems(): for method, action_dict in path_entry_dict['method'].items():
for action in action_dict.get('descriptor', ()): for action in action_dict.get('descriptor', ()):
descriptor_dict = { descriptor_dict = {
'title': action['title'], 'title': action['title'],
...@@ -1000,7 +1011,7 @@ class Application(object): ...@@ -1000,7 +1011,7 @@ class Application(object):
except KeyError: except KeyError:
raise NotFound raise NotFound
else: else:
crl = b'\n'.join(crl_dict.itervalues()) crl = b'\n'.join(crl_dict.values())
return self._returnFile(crl, 'application/pkix-crl') return self._returnFile(crl, 'application/pkix-crl')
def getCSR(self, context, environ, subpath): def getCSR(self, context, environ, subpath):
......
...@@ -67,5 +67,4 @@ setup( ...@@ -67,5 +67,4 @@ setup(
] ]
}, },
test_suite='caucase.test', test_suite='caucase.test',
use_2to3=True,
) )
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment