Merge "Fix and enable H401"

This commit is contained in:
Jenkins
2013-06-28 16:49:23 +00:00
committed by Gerrit Code Review
14 changed files with 65 additions and 63 deletions

View File

@@ -173,7 +173,7 @@ class AccessInfo(dict):
@property @property
def scoped(self): def scoped(self):
""" Returns true if the authorization token was scoped to a tenant """Returns true if the authorization token was scoped to a tenant
(project), and contains a populated service catalog. (project), and contains a populated service catalog.
This is deprecated, use project_scoped instead. This is deprecated, use project_scoped instead.
@@ -184,7 +184,7 @@ class AccessInfo(dict):
@property @property
def project_scoped(self): def project_scoped(self):
""" Returns true if the authorization token was scoped to a tenant """Returns true if the authorization token was scoped to a tenant
(project). (project).
:returns: bool :returns: bool
@@ -193,7 +193,7 @@ class AccessInfo(dict):
@property @property
def domain_scoped(self): def domain_scoped(self):
""" Returns true if the authorization token was scoped to a domain. """Returns true if the authorization token was scoped to a domain.
:returns: bool :returns: bool
""" """

View File

@@ -118,7 +118,8 @@ def is_ans1_token(token):
def cms_sign_text(text, signing_cert_file_name, signing_key_file_name): def cms_sign_text(text, signing_cert_file_name, signing_key_file_name):
""" Uses OpenSSL to sign a document """Uses OpenSSL to sign a document.
Produces a Base64 encoding of a DER formatted CMS Document Produces a Base64 encoding of a DER formatted CMS Document
http://en.wikipedia.org/wiki/Cryptographic_Message_Syntax http://en.wikipedia.org/wiki/Cryptographic_Message_Syntax
""" """

View File

@@ -29,7 +29,7 @@ class EndpointNotFound(Exception):
class EmptyCatalog(Exception): class EmptyCatalog(Exception):
""" The service catalog is empty. """ """The service catalog is empty. """
pass pass

View File

@@ -47,12 +47,12 @@ class Client(client.HTTPClient):
""" """
def __init__(self, endpoint=None, **kwargs): def __init__(self, endpoint=None, **kwargs):
""" Initialize a new client for the Keystone v2.0 API. """ """Initialize a new client for the Keystone v2.0 API."""
super(Client, self).__init__(endpoint=endpoint, **kwargs) super(Client, self).__init__(endpoint=endpoint, **kwargs)
self.endpoint = endpoint self.endpoint = endpoint
def discover(self, url=None): def discover(self, url=None):
""" Discover Keystone servers and return API versions supported. """Discover Keystone servers and return API versions supported.
:param url: optional url to test (without version) :param url: optional url to test (without version)
@@ -74,11 +74,11 @@ class Client(client.HTTPClient):
return self._local_keystone_exists() return self._local_keystone_exists()
def _local_keystone_exists(self): def _local_keystone_exists(self):
""" Checks if Keystone is available on default local port 35357 """ """Checks if Keystone is available on default local port 35357."""
return self._check_keystone_versions("http://localhost:35357") return self._check_keystone_versions("http://localhost:35357")
def _check_keystone_versions(self, url): def _check_keystone_versions(self, url):
""" Calls Keystone URL and detects the available API versions """ """Calls Keystone URL and detects the available API versions."""
try: try:
httpclient = client.HTTPClient() httpclient = client.HTTPClient()
resp, body = httpclient.request(url, "GET", resp, body = httpclient.request(url, "GET",
@@ -125,7 +125,7 @@ class Client(client.HTTPClient):
_logger.exception(e) _logger.exception(e)
def discover_extensions(self, url=None): def discover_extensions(self, url=None):
""" Discover Keystone extensions supported. """Discover Keystone extensions supported.
:param url: optional url to test (should have a version in it) :param url: optional url to test (should have a version in it)
@@ -141,7 +141,7 @@ class Client(client.HTTPClient):
return self._check_keystone_extensions(url) return self._check_keystone_extensions(url)
def _check_keystone_extensions(self, url): def _check_keystone_extensions(self, url):
""" Calls Keystone URL and detects the available extensions """ """Calls Keystone URL and detects the available extensions."""
try: try:
httpclient = client.HTTPClient() httpclient = client.HTTPClient()
if not url.endswith("/"): if not url.endswith("/"):
@@ -184,7 +184,7 @@ class Client(client.HTTPClient):
@staticmethod @staticmethod
def _get_version_info(version, root_url): def _get_version_info(version, root_url):
""" Parses version information """Parses version information.
:param version: a dict of a Keystone version response :param version: a dict of a Keystone version response
:param root_url: string url used to construct :param root_url: string url used to construct
@@ -203,7 +203,7 @@ class Client(client.HTTPClient):
@staticmethod @staticmethod
def _get_extension_info(extension): def _get_extension_info(extension):
""" Parses extension information """Parses extension information.
:param extension: a dict of a Keystone extension response :param extension: a dict of a Keystone extension response
:returns: tuple - (alias, name) :returns: tuple - (alias, name)

View File

@@ -226,7 +226,7 @@ CACHE_KEY_TEMPLATE = 'tokens/%s'
def will_expire_soon(expiry): def will_expire_soon(expiry):
""" Determines if expiration is about to occur. """Determines if expiration is about to occur.
:param expiry: a datetime of the expected expiration :param expiry: a datetime of the expected expiration
:returns: boolean : true if expiration is within 30 seconds :returns: boolean : true if expiration is within 30 seconds
@@ -382,7 +382,7 @@ class AuthProtocol(object):
return CONF.keystone_authtoken[name] return CONF.keystone_authtoken[name]
def _choose_api_version(self): def _choose_api_version(self):
""" Determine the api version that we should use.""" """Determine the api version that we should use."""
# If the configuration specifies an auth_version we will just # If the configuration specifies an auth_version we will just
# assume that is correct and use it. We could, of course, check # assume that is correct and use it. We could, of course, check
@@ -896,7 +896,7 @@ class AuthProtocol(object):
self.LOG.debug('Cached Token %s seems expired', token) self.LOG.debug('Cached Token %s seems expired', token)
def _cache_store(self, token, data): def _cache_store(self, token, data):
""" Store value into memcache. """Store value into memcache.
data may be the string 'invalid' or a tuple like (data, expires) data may be the string 'invalid' or a tuple like (data, expires)
@@ -943,7 +943,7 @@ class AuthProtocol(object):
return expires return expires
def _cache_put(self, token, data, expires): def _cache_put(self, token, data, expires):
""" Put token data into the cache. """Put token data into the cache.
Stores the parsed expire date in cache allowing Stores the parsed expire date in cache allowing
quick check of token freshness on retrieval. quick check of token freshness on retrieval.

View File

@@ -49,7 +49,7 @@ DIGEST_LENGTH_B64 = 4 * int(math.ceil(DIGEST_LENGTH / 3.0))
class InvalidMacError(Exception): class InvalidMacError(Exception):
""" raise when unable to verify MACed data """raise when unable to verify MACed data.
This usually indicates that data had been expectedly modified in memcache. This usually indicates that data had been expectedly modified in memcache.
@@ -58,21 +58,21 @@ class InvalidMacError(Exception):
class DecryptError(Exception): class DecryptError(Exception):
""" raise when unable to decrypt encrypted data """raise when unable to decrypt encrypted data.
""" """
pass pass
class CryptoUnavailableError(Exception): class CryptoUnavailableError(Exception):
""" raise when Python Crypto module is not available """raise when Python Crypto module is not available.
""" """
pass pass
def assert_crypto_availability(f): def assert_crypto_availability(f):
""" Ensure Crypto module is available. """ """Ensure Crypto module is available."""
@functools.wraps(f) @functools.wraps(f)
def wrapper(*args, **kwds): def wrapper(*args, **kwds):
@@ -83,7 +83,7 @@ def assert_crypto_availability(f):
def constant_time_compare(first, second): def constant_time_compare(first, second):
""" Returns True if both string inputs are equal, otherwise False """Returns True if both string inputs are equal, otherwise False.
This function should take a constant amount of time regardless of This function should take a constant amount of time regardless of
how many characters in the strings match. how many characters in the strings match.
@@ -98,7 +98,7 @@ def constant_time_compare(first, second):
def derive_keys(token, secret, strategy): def derive_keys(token, secret, strategy):
""" Derives keys for MAC and ENCRYPTION from the user-provided """Derives keys for MAC and ENCRYPTION from the user-provided
secret. The resulting keys should be passed to the protect and secret. The resulting keys should be passed to the protect and
unprotect functions. unprotect functions.
@@ -118,14 +118,14 @@ def derive_keys(token, secret, strategy):
def sign_data(key, data): def sign_data(key, data):
""" Sign the data using the defined function and the derived key""" """Sign the data using the defined function and the derived key"""
mac = hmac.new(key, data, HASH_FUNCTION).digest() mac = hmac.new(key, data, HASH_FUNCTION).digest()
return base64.b64encode(mac) return base64.b64encode(mac)
@assert_crypto_availability @assert_crypto_availability
def encrypt_data(key, data): def encrypt_data(key, data):
""" Encrypt the data with the given secret key. """Encrypt the data with the given secret key.
Padding is n bytes of the value n, where 1 <= n <= blocksize. Padding is n bytes of the value n, where 1 <= n <= blocksize.
""" """
@@ -137,7 +137,7 @@ def encrypt_data(key, data):
@assert_crypto_availability @assert_crypto_availability
def decrypt_data(key, data): def decrypt_data(key, data):
""" Decrypt the data with the given secret key. """ """Decrypt the data with the given secret key."""
iv = data[:16] iv = data[:16]
cipher = AES.new(key, AES.MODE_CBC, iv) cipher = AES.new(key, AES.MODE_CBC, iv)
try: try:
@@ -152,7 +152,7 @@ def decrypt_data(key, data):
def protect_data(keys, data): def protect_data(keys, data):
""" Given keys and serialized data, returns an appropriately """Given keys and serialized data, returns an appropriately
protected string suitable for storage in the cache. protected string suitable for storage in the cache.
""" """
@@ -166,7 +166,7 @@ def protect_data(keys, data):
def unprotect_data(keys, signed_data): def unprotect_data(keys, signed_data):
""" Given keys and cached string data, verifies the signature, """Given keys and cached string data, verifies the signature,
decrypts if necessary, and returns the original serialized data. decrypts if necessary, and returns the original serialized data.
""" """
@@ -195,7 +195,7 @@ def unprotect_data(keys, signed_data):
def get_cache_key(keys): def get_cache_key(keys):
""" Given keys generated by derive_keys(), returns a base64 """Given keys generated by derive_keys(), returns a base64
encoded value suitable for use as a cache key in memcached. encoded value suitable for use as a cache key in memcached.
""" """

View File

@@ -122,7 +122,7 @@ class Client(client.HTTPClient):
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
""" Initialize a new client for the Keystone v2.0 API. """ """Initialize a new client for the Keystone v2.0 API. """
super(Client, self).__init__(**kwargs) super(Client, self).__init__(**kwargs)
self.version = 'v2.0' self.version = 'v2.0'
self.endpoints = endpoints.EndpointManager(self) self.endpoints = endpoints.EndpointManager(self)
@@ -139,7 +139,7 @@ class Client(client.HTTPClient):
self.authenticate() self.authenticate()
def process_token(self): def process_token(self):
""" Extract and process information from the new auth_ref. """Extract and process information from the new auth_ref.
And set the relevant authentication information. And set the relevant authentication information.
""" """
@@ -170,7 +170,7 @@ class Client(client.HTTPClient):
tenant_id=None, token=None, tenant_id=None, token=None,
project_name=None, project_id=None, project_name=None, project_id=None,
**kwargs): **kwargs):
""" Authenticate against the v2 Identity API. """Authenticate against the v2 Identity API.
:returns: (``resp``, ``body``) if authentication was successful. :returns: (``resp``, ``body``) if authentication was successful.
:raises: AuthorizationFailure if unable to authenticate or validate :raises: AuthorizationFailure if unable to authenticate or validate
@@ -194,7 +194,7 @@ class Client(client.HTTPClient):
def _base_authN(self, auth_url, username=None, password=None, def _base_authN(self, auth_url, username=None, password=None,
tenant_name=None, tenant_id=None, token=None): tenant_name=None, tenant_id=None, token=None):
""" Takes a username, password, and optionally a tenant_id or """Takes a username, password, and optionally a tenant_id or
tenant_name to get an authentication token from keystone. tenant_name to get an authentication token from keystone.
May also take a token and a tenant_id to re-scope a token May also take a token and a tenant_id to re-scope a token
to a tenant.""" to a tenant."""

View File

@@ -62,7 +62,7 @@ class RoleManager(base.ManagerWithFind):
return self._list("/users/%s/roles" % user_id, "roles") return self._list("/users/%s/roles" % user_id, "roles")
def add_user_role(self, user, role, tenant=None): def add_user_role(self, user, role, tenant=None):
""" Adds a role to a user. """Adds a role to a user.
If tenant is specified, the role is added just for that tenant, If tenant is specified, the role is added just for that tenant,
otherwise the role is added globally. otherwise the role is added globally.
@@ -78,7 +78,7 @@ class RoleManager(base.ManagerWithFind):
return self._update(route % (user_id, role_id), None, "roles") return self._update(route % (user_id, role_id), None, "roles")
def remove_user_role(self, user, role, tenant=None): def remove_user_role(self, user, role, tenant=None):
""" Removes a role from a user. """Removes a role from a user.
If tenant is specified, the role is removed just for that tenant, If tenant is specified, the role is removed just for that tenant,
otherwise the role is removed from the user's global roles. otherwise the role is removed from the user's global roles.

View File

@@ -140,17 +140,17 @@ class TenantManager(base.ManagerWithFind):
return self._delete("/tenants/%s" % (base.getid(tenant))) return self._delete("/tenants/%s" % (base.getid(tenant)))
def list_users(self, tenant): def list_users(self, tenant):
""" List users for a tenant. """ """List users for a tenant. """
return self.api.users.list(base.getid(tenant)) return self.api.users.list(base.getid(tenant))
def add_user(self, tenant, user, role): def add_user(self, tenant, user, role):
""" Add a user to a tenant with the given role. """ """Add a user to a tenant with the given role. """
return self.api.roles.add_user_role(base.getid(user), return self.api.roles.add_user_role(base.getid(user),
base.getid(role), base.getid(role),
base.getid(tenant)) base.getid(tenant))
def remove_user(self, tenant, user, role): def remove_user(self, tenant, user, role):
""" Remove the specified role from the user on the tenant. """ """Remove the specified role from the user on the tenant. """
return self.api.roles.remove_user_role(base.getid(user), return self.api.roles.remove_user_role(base.getid(user),
base.getid(role), base.getid(role),
base.getid(tenant)) base.getid(tenant))

View File

@@ -84,7 +84,7 @@ class Client(client.Client):
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
""" Initialize a new client for the Keystone v3 API. """ """Initialize a new client for the Keystone v3 API."""
super(Client, self).__init__(**kwargs) super(Client, self).__init__(**kwargs)
self.version = 'v3' self.version = 'v3'
@@ -102,7 +102,7 @@ class Client(client.Client):
return json.dumps(entity, sort_keys=True) return json.dumps(entity, sort_keys=True)
def process_token(self): def process_token(self):
""" Extract and process information from the new auth_ref. """Extract and process information from the new auth_ref.
And set the relevant authentication information. And set the relevant authentication information.
""" """
@@ -126,7 +126,7 @@ class Client(client.Client):
project_domain_id=None, project_domain_id=None,
project_domain_name=None, project_domain_name=None,
token=None, **kwargs): token=None, **kwargs):
""" Authenticate against the v3 Identity API. """Authenticate against the v3 Identity API.
:returns: (``resp``, ``body``) if authentication was successful. :returns: (``resp``, ``body``) if authentication was successful.
:raises: AuthorizationFailure if unable to authenticate or validate :raises: AuthorizationFailure if unable to authenticate or validate

View File

@@ -368,7 +368,7 @@ VERSION_LIST_v2 = {
class NoModuleFinder(object): class NoModuleFinder(object):
""" Disallow further imports of 'module' """ """Disallow further imports of 'module'."""
def __init__(self, module): def __init__(self, module):
self.module = module self.module = module
@@ -433,7 +433,7 @@ class FakeHTTPResponse(object):
class BaseFakeHTTPConnection(object): class BaseFakeHTTPConnection(object):
def _user_token_responses(self, token_id): def _user_token_responses(self, token_id):
""" Emulate user token responses. """Emulate user token responses.
Return success if the token is in the list we know Return success if the token is in the list we know
about. If the request is for revoked tokens, then return about. If the request is for revoked tokens, then return
@@ -473,7 +473,7 @@ class BaseFakeHTTPConnection(object):
class FakeHTTPConnection(BaseFakeHTTPConnection): class FakeHTTPConnection(BaseFakeHTTPConnection):
""" Emulate a fake Keystone v2 server """ """Emulate a fake Keystone v2 server."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.send_valid_revocation_list = True self.send_valid_revocation_list = True
@@ -519,7 +519,7 @@ class FakeHTTPConnection(BaseFakeHTTPConnection):
class v3FakeHTTPConnection(FakeHTTPConnection): class v3FakeHTTPConnection(FakeHTTPConnection):
""" Emulate a fake Keystone v3 server """ """Emulate a fake Keystone v3 server."""
def request(self, method, path, **kwargs): def request(self, method, path, **kwargs):
"""Fakes out several http responses. """Fakes out several http responses.
@@ -549,7 +549,7 @@ class v3FakeHTTPConnection(FakeHTTPConnection):
class RaisingHTTPConnection(FakeHTTPConnection): class RaisingHTTPConnection(FakeHTTPConnection):
""" An HTTPConnection that always raises.""" """An HTTPConnection that always raises."""
def request(self, method, path, **kwargs): def request(self, method, path, **kwargs):
raise AssertionError("HTTP request was called.") raise AssertionError("HTTP request was called.")
@@ -599,7 +599,7 @@ class v3FakeApp(object):
class BaseAuthTokenMiddlewareTest(testtools.TestCase): class BaseAuthTokenMiddlewareTest(testtools.TestCase):
""" Base test class for auth_token middleware. """Base test class for auth_token middleware.
All the tests allow for running with auth_token All the tests allow for running with auth_token
configured for receiving v2 or v3 tokens, with the configured for receiving v2 or v3 tokens, with the
@@ -651,7 +651,7 @@ class BaseAuthTokenMiddlewareTest(testtools.TestCase):
globals()[signed_list] = globals()[valid_signed_list] globals()[signed_list] = globals()[valid_signed_list]
def set_fake_http(self, http_handler): def set_fake_http(self, http_handler):
""" Configure the http handler for the auth_token middleware. """Configure the http handler for the auth_token middleware.
Allows tests to override the default handler on specific tests, Allows tests to override the default handler on specific tests,
e.g. to use v2 for those parts of auth_token that still use v2 e.g. to use v2 for those parts of auth_token that still use v2
@@ -663,7 +663,7 @@ class BaseAuthTokenMiddlewareTest(testtools.TestCase):
def set_middleware(self, fake_app=None, fake_http=None, def set_middleware(self, fake_app=None, fake_http=None,
expected_env=None, conf=None): expected_env=None, conf=None):
""" Configure the class ready to call the auth_token middleware. """Configure the class ready to call the auth_token middleware.
Set up the various fake items needed to run the middleware. Set up the various fake items needed to run the middleware.
Individual tests that need to further refine these can call this Individual tests that need to further refine these can call this
@@ -1197,7 +1197,7 @@ class AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest): class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
""" v2 token specific tests. """v2 token specific tests.
There are some differences between how the auth-token middleware handles There are some differences between how the auth-token middleware handles
v2 and v3 tokens over and above the token formats, namely: v2 and v3 tokens over and above the token formats, namely:
@@ -1256,7 +1256,7 @@ class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
self.assertEqual(body, ['SUCCESS']) self.assertEqual(body, ['SUCCESS'])
def test_valid_uuid_request_forced_to_2_0(self): def test_valid_uuid_request_forced_to_2_0(self):
""" Test forcing auth_token to use lower api version. """Test forcing auth_token to use lower api version.
By installing the v3 http hander, auth_token will be get By installing the v3 http hander, auth_token will be get
a version list that looks like a v3 server - from which it a version list that looks like a v3 server - from which it
@@ -1294,7 +1294,7 @@ class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
class v3AuthTokenMiddlewareTest(AuthTokenMiddlewareTest): class v3AuthTokenMiddlewareTest(AuthTokenMiddlewareTest):
""" Test auth_token middleware with v3 tokens. """Test auth_token middleware with v3 tokens.
Re-execute the AuthTokenMiddlewareTest class tests, but with the Re-execute the AuthTokenMiddlewareTest class tests, but with the
the auth_token middleware configured to expect v3 tokens back from the auth_token middleware configured to expect v3 tokens back from

View File

@@ -94,7 +94,7 @@ class TestCase(testtools.TestCase):
class UnauthenticatedTestCase(testtools.TestCase): class UnauthenticatedTestCase(testtools.TestCase):
""" Class used as base for unauthenticated calls """ """Class used as base for unauthenticated calls."""
TEST_ROOT_URL = 'http://127.0.0.1:5000/' TEST_ROOT_URL = 'http://127.0.0.1:5000/'
TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v2.0') TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v2.0')
TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/'
@@ -122,8 +122,9 @@ class UnauthenticatedTestCase(testtools.TestCase):
class TestResponse(requests.Response): class TestResponse(requests.Response):
""" Class used to wrap requests.Response and provide some """Class used to wrap requests.Response and provide some
convenience to initialize with a dict """ convenience to initialize with a dict.
"""
def __init__(self, data): def __init__(self, data):
self._text = None self._text = None

View File

@@ -149,7 +149,7 @@ class TestCase(testtools.TestCase):
class UnauthenticatedTestCase(testtools.TestCase): class UnauthenticatedTestCase(testtools.TestCase):
""" Class used as base for unauthenticated calls """ """Class used as base for unauthenticated calls """
TEST_ROOT_URL = 'http://127.0.0.1:5000/' TEST_ROOT_URL = 'http://127.0.0.1:5000/'
TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3')
TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/'
@@ -364,8 +364,9 @@ class CrudTests(testtools.TestCase):
class TestResponse(requests.Response): class TestResponse(requests.Response):
""" Class used to wrap requests.Response and provide some """Class used to wrap requests.Response and provide some
convenience to initialize with a dict """ convenience to initialize with a dict.
"""
def __init__(self, data): def __init__(self, data):
self._text = None self._text = None

View File

@@ -35,11 +35,10 @@ downloadcache = ~/cache/pip
# H302: import only modules # H302: import only modules
# H304: no relative imports # H304: no relative imports
# H306: imports not in alphabetical order # H306: imports not in alphabetical order
# H401: docstring should not start with a space
# H402: one line docstring needs punctuation. # H402: one line docstring needs punctuation.
# H403: multi line docstring end on new line # H403: multi line docstring end on new line
# H404: multi line docstring should start with a summary # H404: multi line docstring should start with a summary
# H802: git commit title # H802: git commit title
ignore = F811,F821,F841,H201,H202,H302,H304,H306,H401,H402,H403,H404,H802 ignore = F811,F821,F841,H201,H202,H302,H304,H306,H402,H403,H404,H802
show-source = True show-source = True
exclude = .venv,.tox,dist,doc,*egg exclude = .venv,.tox,dist,doc,*egg