Merge pull request #30 from kevgliss/py3

Making Lemur py3 compatible
This commit is contained in:
kevgliss 2015-08-03 21:20:59 -07:00
commit 3ebbbd21e7
16 changed files with 81 additions and 87 deletions

View File

@ -1,23 +1,36 @@
sudo: false
language: python
addons:
postgresql: "9.4"
python:
- "2.7"
matrix:
include:
- python: "2.7"
env: TOXENV=py27
- python: "3.3"
env: TOXENV=py33
- python: "3.4"
env: TOXENV=py34
cache:
directories:
- node_modules
- .pip_download_cache
- "$HOME/virtualenv/python2.7.9"
env:
global:
- PIP_DOWNLOAD_CACHE=".pip_download_cache"
install:
- make dev-postgres
before_script:
- psql -c "create database lemur;" -U postgres
- psql -c "create user lemur with password 'lemur;'" -U postgres
- npm install -g bower
script:
- make test

View File

@ -1,5 +1,5 @@
"""
.. module: permissions
.. module: lemur.auth.permissions
:platform: Unix
:synopsis: This module defines all the permission used within Lemur
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
@ -24,15 +24,15 @@ CertificateOwnerNeed = partial(CertificateOwner, 'certificateView')
class ViewKeyPermission(Permission):
def __init__(self, role_id, certificate_id):
c_need = CertificateCreatorNeed(unicode(certificate_id))
o_need = CertificateOwnerNeed(unicode(role_id))
c_need = CertificateCreatorNeed(str(certificate_id))
o_need = CertificateOwnerNeed(str(role_id))
super(ViewKeyPermission, self).__init__(o_need, c_need, RoleNeed('admin'))
class UpdateCertificatePermission(Permission):
def __init__(self, role_id, certificate_id):
c_need = CertificateCreatorNeed(unicode(certificate_id))
o_need = CertificateOwnerNeed(unicode(role_id))
c_need = CertificateCreatorNeed(str(certificate_id))
o_need = CertificateOwnerNeed(str(role_id))
super(UpdateCertificatePermission, self).__init__(o_need, c_need, RoleNeed('admin'))
@ -42,7 +42,7 @@ ViewRoleCredentialsNeed = partial(RoleUser, 'roleView')
class ViewRoleCredentialsPermission(Permission):
def __init__(self, role_id):
need = ViewRoleCredentialsNeed(unicode(role_id))
need = ViewRoleCredentialsNeed(str(role_id))
super(ViewRoleCredentialsPermission, self).__init__(need, RoleNeed('admin'))
@ -55,8 +55,8 @@ AuthorityOwnerNeed = partial(AuthorityOwner, 'role')
class AuthorityPermission(Permission):
def __init__(self, authority_id, roles):
needs = [RoleNeed('admin'), AuthorityCreatorNeed(unicode(authority_id))]
needs = [RoleNeed('admin'), AuthorityCreatorNeed(str(authority_id))]
for r in roles:
needs.append(AuthorityOwnerNeed(unicode(r)))
needs.append(AuthorityOwnerNeed(str(r)))
super(AuthorityPermission, self).__init__(*needs)

View File

@ -12,6 +12,8 @@ import jwt
import json
import base64
import binascii
from builtins import str
from functools import wraps
from datetime import datetime, timedelta
@ -32,7 +34,7 @@ from lemur.auth.permissions import CertificateOwnerNeed, CertificateCreatorNeed,
def base64url_decode(data):
if isinstance(data, unicode):
if isinstance(data, str):
data = str(data)
rem = len(data) % 4
@ -139,7 +141,9 @@ def fetch_token_header(token):
try:
return json.loads(base64url_decode(header_segment))
except TypeError, binascii.Error:
except TypeError:
raise jwt.DecodeError('Invalid header padding')
except binascii.Error:
raise jwt.DecodeError('Invalid header padding')
@ -161,19 +165,19 @@ def on_identity_loaded(sender, identity):
# identity with the roles that the user provides
if hasattr(user, 'roles'):
for role in user.roles:
identity.provides.add(CertificateOwnerNeed(unicode(role.id)))
identity.provides.add(ViewRoleCredentialsNeed(unicode(role.id)))
identity.provides.add(CertificateOwnerNeed(role.id))
identity.provides.add(ViewRoleCredentialsNeed(role.id))
identity.provides.add(RoleNeed(role.name))
# apply ownership for authorities
if hasattr(user, 'authorities'):
for authority in user.authorities:
identity.provides.add(AuthorityCreatorNeed(unicode(authority.id)))
identity.provides.add(AuthorityCreatorNeed(authority.id))
# apply ownership of certificates
if hasattr(user, 'certificates'):
for certificate in user.certificates:
identity.provides.add(CertificateCreatorNeed(unicode(certificate.id)))
identity.provides.add(CertificateCreatorNeed(certificate.id))
g.user = user

View File

@ -7,6 +7,7 @@
"""
import os
import datetime
from cryptography import x509
from cryptography.hazmat.backends import default_backend
@ -56,7 +57,10 @@ def create_name(issuer, not_before, not_after, subject, san):
disallowed_chars = disallowed_chars.replace("-", "")
disallowed_chars = disallowed_chars.replace(".", "")
temp = temp.replace('*', "WILDCARD")
temp = temp.translate(None, disallowed_chars)
for c in disallowed_chars:
temp = temp.replace(c, "")
# white space is silly too
return temp.replace(" ", "-")
@ -151,7 +155,9 @@ def cert_get_issuer(cert):
delchars = ''.join(c for c in map(chr, range(256)) if not c.isalnum())
try:
issuer = str(cert.issuer.get_attributes_for_oid(x509.OID_ORGANIZATION_NAME)[0].value)
return issuer.translate(None, delchars)
for c in delchars:
issuer = issuer.replace(c, "")
return issuer
except Exception as e:
current_app.logger.error("Unable to get issuer! {0}".format(e))

View File

@ -304,15 +304,15 @@ def create_csr(csr_config):
backend=default_backend()
)
# TODO When we figure out a better way to validate these options they should be parsed as unicode
# TODO When we figure out a better way to validate these options they should be parsed as str
builder = x509.CertificateSigningRequestBuilder()
builder = builder.subject_name(x509.Name([
x509.NameAttribute(x509.OID_COMMON_NAME, unicode(csr_config['commonName'])),
x509.NameAttribute(x509.OID_ORGANIZATION_NAME, unicode(csr_config['organization'])),
x509.NameAttribute(x509.OID_ORGANIZATIONAL_UNIT_NAME, unicode(csr_config['organizationalUnit'])),
x509.NameAttribute(x509.OID_COUNTRY_NAME, unicode(csr_config['country'])),
x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, unicode(csr_config['state'])),
x509.NameAttribute(x509.OID_LOCALITY_NAME, unicode(csr_config['location'])),
x509.NameAttribute(x509.OID_COMMON_NAME, csr_config['commonName']),
x509.NameAttribute(x509.OID_ORGANIZATION_NAME, csr_config['organization']),
x509.NameAttribute(x509.OID_ORGANIZATIONAL_UNIT_NAME, csr_config['organizationalUnit']),
x509.NameAttribute(x509.OID_COUNTRY_NAME, csr_config['country']),
x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, csr_config['state']),
x509.NameAttribute(x509.OID_LOCALITY_NAME, csr_config['location']),
]))
builder = builder.add_extension(

View File

@ -5,6 +5,8 @@
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
from builtins import str
from flask import Blueprint, make_response, jsonify
from flask.ext.restful import reqparse, Api, fields
@ -75,7 +77,7 @@ def pem_str(value, name):
:return: :raise ValueError:
"""
try:
x509.load_pem_x509_certificate(str(value), default_backend())
x509.load_pem_x509_certificate(bytes(value), default_backend())
except Exception:
raise ValueError("The parameter '{0}' needs to be a valid PEM string".format(name))
return value
@ -90,7 +92,7 @@ def private_key_str(value, name):
:return: :raise ValueError:
"""
try:
serialization.load_pem_private_key(str(value), None, backend=default_backend())
serialization.load_pem_private_key(bytes(value), None, backend=default_backend())
except Exception:
raise ValueError("The parameter '{0}' needs to be a valid RSA private key".format(name))
return value

View File

@ -65,7 +65,7 @@ class marshal_items(object):
else:
return {'message': 'unknown'}, 400
else:
return {'message': e.message}, 400
return {'message': str(e)}, 400
return wrapper

View File

@ -3,6 +3,8 @@
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
"""
from builtins import str
from datetime import timedelta
from flask import make_response, request, current_app
@ -16,10 +18,10 @@ def crossdomain(origin=None, methods=None, headers=None,
if methods is not None:
methods = ', '.join(sorted(x.upper() for x in methods))
if headers is not None and not isinstance(headers, basestring):
if headers is not None and not isinstance(headers, str):
headers = ', '.join(x.upper() for x in headers)
if not isinstance(origin, basestring):
if not isinstance(origin, str):
origin = ', '.join(origin)
if isinstance(max_age, timedelta):

View File

@ -1,5 +1,5 @@
try:
VERSION = __import__('pkg_resources') \
.get_distribution(__name__).version
except Exception, e:
except Exception as e:
VERSION = 'unknown'

View File

@ -1,5 +1,5 @@
try:
VERSION = __import__('pkg_resources') \
.get_distribution(__name__).version
except Exception, e:
except Exception as e:
VERSION = 'unknown'

View File

@ -1,5 +1,5 @@
try:
VERSION = __import__('pkg_resources') \
.get_distribution(__name__).version
except Exception, e:
except Exception as e:
VERSION = 'unknown'

View File

@ -1,5 +1,5 @@
try:
VERSION = __import__('pkg_resources') \
.get_distribution(__name__).version
except Exception, e:
except Exception as e:
VERSION = 'unknown'

View File

@ -1,7 +1,7 @@
from cryptography import x509
from cryptography.hazmat.backends import default_backend
INTERNAL_VALID_LONG_STR = """
INTERNAL_VALID_LONG_STR = b"""
-----BEGIN CERTIFICATE-----
MIID1zCCAr+gAwIBAgIBATANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCVVMx
CzAJBgNVBAgMAkNBMRAwDgYDVQQHDAdBIHBsYWNlMRcwFQYDVQQDDA5sb25nLmxp
@ -29,7 +29,7 @@ h0S8LN4iv/+vNFPNiM1z9X/SZgfbwZXrLsSi
INTERNAL_VALID_LONG_CERT = x509.load_pem_x509_certificate(INTERNAL_VALID_LONG_STR, default_backend())
INTERNAL_INVALID_STR = """
INTERNAL_INVALID_STR = b"""
-----BEGIN CERTIFICATE-----
MIIEFTCCAv2gAwIBAgICA+gwDQYJKoZIhvcNAQELBQAwgYwxCzAJBgNVBAYTAlVT
MQswCQYDVQQIDAJDQTEQMA4GA1UEBwwHQSBwbGFjZTEXMBUGA1UEAwwObG9uZy5s
@ -58,7 +58,7 @@ kP+oGWtHvhteUAe8Gloo5NchZJ0/BqlYRCD5aAHcmbXRsDid9mO4ADU=
INTERNAL_INVALID_CERT = x509.load_pem_x509_certificate(INTERNAL_INVALID_STR, default_backend())
INTERNAL_VALID_SAN_STR = """
INTERNAL_VALID_SAN_STR = b"""
-----BEGIN CERTIFICATE-----
MIIESjCCAzKgAwIBAgICA+kwDQYJKoZIhvcNAQELBQAwgYwxCzAJBgNVBAYTAlVT
MQswCQYDVQQIDAJDQTEQMA4GA1UEBwwHQSBwbGFjZTEXMBUGA1UEAwwObG9uZy5s
@ -88,7 +88,7 @@ YBrY/duF15YpoMKAlFhDBh6R9/nb5kI2n3pY6I5h6LEYfLStazXbIu61M8zu9TM/
INTERNAL_VALID_SAN_CERT = x509.load_pem_x509_certificate(INTERNAL_VALID_SAN_STR, default_backend())
INTERNAL_VALID_WILDCARD_STR = """
INTERNAL_VALID_WILDCARD_STR = b"""
-----BEGIN CERTIFICATE-----
MIIEHDCCAwSgAwIBAgICA+owDQYJKoZIhvcNAQELBQAwgYwxCzAJBgNVBAYTAlVT
MQswCQYDVQQIDAJDQTEQMA4GA1UEBwwHQSBwbGFjZTEXMBUGA1UEAwwObG9uZy5s
@ -117,7 +117,7 @@ S0Xb3ZauZJQI7OdHeUPDRVq+8hcG77sopN9pEYrIH08oxvLX2US3GqrowjOxthRa
INTERNAL_VALID_WILDCARD_CERT = x509.load_pem_x509_certificate(INTERNAL_VALID_WILDCARD_STR, default_backend())
EXTERNAL_VALID_STR = """
EXTERNAL_VALID_STR = b"""
-----BEGIN CERTIFICATE-----
MIIFHzCCBAegAwIBAgIQGFWCciDWzbOej/TbAJN0WzANBgkqhkiG9w0BAQsFADCB
pDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8w
@ -152,7 +152,7 @@ Bs63gULVCqWygt5KEbv990m/XGuRMaXuHzHCHB4v5LRM30FiFmqCzyD8d+btzW9B
EXTERNAL_CERT = x509.load_pem_x509_certificate(EXTERNAL_VALID_STR, default_backend())
PRIVATE_KEY_STR = """
PRIVATE_KEY_STR = b"""
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAnEjM0cQevlDjT6mDMtTo8N1ovAyKbfVEp0ketCPC4hLkStms
q9ETIyyerARIMv4SEhKqS4E7HIg6ccGkwv1ja5E/b2jHMH4ht1dEXnfM2yh0Mwvk
@ -181,41 +181,3 @@ t5Gpocpt77LJnNiszXSerj/KjX2MflY5xUXeekWowLVTBOK5+CZ8+XBIgBt1hIG3
XKxcRgm/Va4QMEAnec0qXfdTVJaJiAW0bdKwKRRrrbwcTdNRGibdng==
-----END RSA PRIVATE KEY-----
"""
CSR_CONFIG = """
# Configuration for standard CSR generation for Netflix
# Used for procuring VeriSign certificates
# Author: jbob
# Contact: security@example.com
[ req ]
# Use a 2048 bit private key
default_bits = 2048
default_keyfile = key.pem
prompt = no
encrypt_key = no
# base request
distinguished_name = req_distinguished_name
# extensions
# Uncomment the following line if you are requesting a SAN cert
#req_extensions = req_ext
# distinguished_name
[ req_distinguished_name ]
countryName = "US" # C=
stateOrProvinceName = "CALIFORNIA" # ST=
localityName = "A place" # L=
organizationName = "Example, Inc." # O=
organizationalUnitName = "Operations" # OU=
# This is the hostname/subject name on the certificate
commonName = "example.net" # CN=
[ req_ext ]
# Uncomment the following line if you are requesting a SAN cert
#subjectAltName = @alt_names
[alt_names]
# Put your SANs here
"""

View File

@ -1,3 +1,5 @@
from __future__ import unicode_literals # at top of module
import pytest
from lemur.certificates.views import * # noqa
@ -21,13 +23,13 @@ def test_private_key_str():
def test_create_basic_csr():
from lemur.certificates.service import create_csr
csr_config = dict(
commonName=u'example.com',
organization=u'Example, Inc.',
organizationalUnit=u'Operations',
country=u'US',
state=u'CA',
location=u'A place',
extensions=dict(names=dict(subAltNames=[u'test.example.com', u'test2.example.com']))
commonName='example.com',
organization='Example, Inc.',
organizationalUnit='Operations',
country='US',
state='CA',
location='A place',
extensions=dict(names=dict(subAltNames=['test.example.com', 'test2.example.com']))
)
csr, pem = create_csr(csr_config)

View File

@ -43,7 +43,8 @@ install_requires = [
'pyopenssl==0.15.1',
'pyjwt==1.0.1',
'xmltodict==0.9.2',
'lockfile==0.10.2'
'lockfile==0.10.2',
'future==0.15.0',
]
tests_require = [

2
tox.ini Normal file
View File

@ -0,0 +1,2 @@
[tox]
envlist = py27,pypy,py33,py34