Simplify code.
Per Termie's suggestion, share as much as possible with ec2 module and instantiate s3 module from it.
This commit is contained in:
parent
fcea15df2a
commit
b1cd21426c
|
@ -26,8 +26,10 @@ from keystone import catalog
|
|||
from keystone import config
|
||||
from keystone import identity
|
||||
from keystone import policy
|
||||
from keystone import service
|
||||
from keystone import token
|
||||
from keystone.common import manager
|
||||
from keystone.common import utils
|
||||
from keystone.common import wsgi
|
||||
|
||||
|
||||
|
@ -52,7 +54,7 @@ class Ec2Extension(wsgi.ExtensionRouter):
|
|||
# validation
|
||||
mapper.connect('/ec2tokens',
|
||||
controller=ec2_controller,
|
||||
action='authenticate_ec2',
|
||||
action='authenticate',
|
||||
conditions=dict(method=['POST']))
|
||||
|
||||
# crud
|
||||
|
@ -83,7 +85,24 @@ class Ec2Controller(wsgi.Application):
|
|||
self.ec2_api = Manager()
|
||||
super(Ec2Controller, self).__init__()
|
||||
|
||||
def authenticate_ec2(self, context, credentials=None,
|
||||
def check_signature(self, creds_ref, credentials):
|
||||
signer = utils.Signer(creds_ref['secret'])
|
||||
signature = signer.generate(credentials)
|
||||
if signature == credentials['signature']:
|
||||
return
|
||||
# NOTE(vish): Some libraries don't use the port when signing
|
||||
# requests, so try again without port.
|
||||
elif ':' in credentials['signature']:
|
||||
hostname, _port = credentials['host'].split(":")
|
||||
credentials['host'] = hostname
|
||||
signature = signer.generate(credentials)
|
||||
if signature != credentials.signature:
|
||||
# TODO(termie): proper exception
|
||||
raise Exception("Not Authorized")
|
||||
else:
|
||||
raise Exception("Not Authorized")
|
||||
|
||||
def authenticate(self, context, credentials=None,
|
||||
ec2Credentials=None):
|
||||
"""Validate a signed EC2 request and provide a token.
|
||||
|
||||
|
@ -113,27 +132,17 @@ class Ec2Controller(wsgi.Application):
|
|||
creds_ref = self.ec2_api.get_credential(context,
|
||||
credentials['access'])
|
||||
|
||||
signer = utils.Signer(creds_ref['secret'])
|
||||
signature = signer.generate(credentials)
|
||||
if signature == credentials['signature']:
|
||||
pass
|
||||
# NOTE(vish): Some libraries don't use the port when signing
|
||||
# requests, so try again without port.
|
||||
elif ':' in credentials['signature']:
|
||||
hostname, _port = credentials['host'].split(":")
|
||||
credentials['host'] = hostname
|
||||
signature = signer.generate(credentials)
|
||||
if signature != credentials.signature:
|
||||
# TODO(termie): proper exception
|
||||
raise Exception("Not Authorized")
|
||||
else:
|
||||
raise Exception("Not Authorized")
|
||||
self.check_signature(creds_ref, credentials)
|
||||
|
||||
# TODO(termie): don't create new tokens every time
|
||||
# TODO(termie): this is copied from TokenController.authenticate
|
||||
token_id = uuid.uuid4().hex
|
||||
tenant_ref = self.identity_api.get_tenant(creds_ref['tenant_id'])
|
||||
user_ref = self.identity_api.get_user(creds_ref['user_id'])
|
||||
tenant_ref = self.identity_api.get_tenant(
|
||||
context=context,
|
||||
tenant_id=creds_ref['tenant_id'])
|
||||
user_ref = self.identity_api.get_user(
|
||||
context=context,
|
||||
user_id=creds_ref['user_id'])
|
||||
metadata_ref = self.identity_api.get_metadata(
|
||||
context=context,
|
||||
user_id=user_ref['id'],
|
||||
|
@ -162,8 +171,9 @@ class Ec2Controller(wsgi.Application):
|
|||
# TODO(termie): i don't think the ec2 middleware currently expects a
|
||||
# full return, but it contains a note saying that it
|
||||
# would be better to expect a full return
|
||||
return TokenController._format_authenticate(
|
||||
self, token_ref, roles_ref, catalog_ref)
|
||||
token_controller = service.TokenController()
|
||||
return token_controller._format_authenticate(
|
||||
token_ref, roles_ref, catalog_ref)
|
||||
|
||||
def create_credential(self, context, user_id, tenant_id):
|
||||
"""Create a secret/access pair for use with ec2 style auth.
|
||||
|
|
|
@ -5,94 +5,39 @@
|
|||
TODO-DOCS
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import base64
|
||||
import hmac
|
||||
|
||||
from hashlib import sha1
|
||||
from keystone import catalog
|
||||
|
||||
from keystone import config
|
||||
from keystone import identity
|
||||
from keystone import policy
|
||||
from keystone import token
|
||||
from keystone import service
|
||||
from keystone.common import wsgi
|
||||
from keystone.contrib.ec2 import Manager as EC2Manager
|
||||
from keystone.contrib import ec2
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
def check_signature(creds_ref, credentials):
|
||||
signature = credentials['signature']
|
||||
msg = base64.urlsafe_b64decode(str(credentials['token']))
|
||||
key = str(creds_ref['secret'])
|
||||
signed = base64.encodestring(hmac.new(key, msg, sha1).digest()).strip()
|
||||
|
||||
if signature == signed:
|
||||
pass
|
||||
else:
|
||||
raise Exception("Not Authorized")
|
||||
|
||||
|
||||
class S3Extension(wsgi.ExtensionRouter):
|
||||
def add_routes(self, mapper):
|
||||
s3_controller = S3Controller()
|
||||
controller = ec2.Ec2Controller()
|
||||
controller.check_signature = check_signature
|
||||
# validation
|
||||
mapper.connect('/s3tokens',
|
||||
controller=s3_controller,
|
||||
action='authenticate_s3',
|
||||
controller=controller,
|
||||
action='authenticate',
|
||||
conditions=dict(method=['POST']))
|
||||
|
||||
# No need CRUD stuff since we are sharing keystone.contrib.ec2
|
||||
# infos.
|
||||
|
||||
|
||||
class S3Controller(wsgi.Application):
|
||||
def __init__(self):
|
||||
self.catalog_api = catalog.Manager()
|
||||
self.identity_api = identity.Manager()
|
||||
self.token_api = token.Manager()
|
||||
self.policy_api = policy.Manager()
|
||||
self.ec2_api = EC2Manager()
|
||||
super(S3Controller, self).__init__()
|
||||
|
||||
def authenticate_s3(self, context, credentials=None):
|
||||
"""Validate a signed S3 request and provide a token.
|
||||
|
||||
TODO-DOCS::
|
||||
|
||||
:param context: standard context
|
||||
:param credentials: dict of s3 signature
|
||||
:returns: token: openstack token equivalent to access key along
|
||||
with the corresponding service catalog and roles
|
||||
"""
|
||||
|
||||
creds_ref = self.ec2_api.get_credential(context,
|
||||
credentials['access'])
|
||||
|
||||
msg = base64.urlsafe_b64decode(str(credentials['token']))
|
||||
key = str(creds_ref['secret'])
|
||||
s = base64.encodestring(hmac.new(key, msg, sha1).digest()).strip()
|
||||
signature = credentials['signature']
|
||||
if signature == s:
|
||||
pass
|
||||
else:
|
||||
raise Exception("Not Authorized")
|
||||
|
||||
token_id = uuid.uuid4().hex
|
||||
tenant_ref = self.identity_api.get_tenant(context,
|
||||
creds_ref['tenant_id'])
|
||||
user_ref = self.identity_api.get_user(context,
|
||||
creds_ref['user_id'])
|
||||
metadata_ref = self.identity_api.get_metadata(
|
||||
context=context,
|
||||
user_id=user_ref['id'],
|
||||
tenant_id=tenant_ref['id'])
|
||||
catalog_ref = self.catalog_api.get_catalog(
|
||||
context=context,
|
||||
user_id=user_ref['id'],
|
||||
tenant_id=tenant_ref['id'],
|
||||
metadata=metadata_ref)
|
||||
|
||||
token_ref = self.token_api.create_token(
|
||||
context, token_id, dict(expires='',
|
||||
id=token_id,
|
||||
user=user_ref,
|
||||
tenant=tenant_ref,
|
||||
metadata=metadata_ref))
|
||||
|
||||
roles_ref = []
|
||||
for role_id in metadata_ref.get('roles', []):
|
||||
roles_ref.append(self.identity_api.get_role(context, role_id))
|
||||
|
||||
token_controller = service.TokenController()
|
||||
return token_controller._format_authenticate(
|
||||
token_ref, roles_ref, catalog_ref)
|
||||
|
|
Loading…
Reference in New Issue