Add a way to create a signed URL from a queue
Add a new signed_url method on v2 Queue object which returns a signature for that queue, and add a new auth backend which can use that signature. Change-Id: Iceb3cd0ab99a5a53d54ab79172c6228c4e239d8c
This commit is contained in:
parent
8962837f88
commit
80474c762d
@ -16,10 +16,12 @@
|
||||
|
||||
from zaqarclient.auth import base
|
||||
from zaqarclient.auth import keystone
|
||||
from zaqarclient.auth import signed_url
|
||||
|
||||
_BACKENDS = {
|
||||
'noauth': base.NoAuth,
|
||||
'keystone': keystone.KeystoneAuth
|
||||
'keystone': keystone.KeystoneAuth,
|
||||
'signed-url': signed_url.SignedURLAuth,
|
||||
}
|
||||
|
||||
|
||||
|
40
zaqarclient/auth/signed_url.py
Normal file
40
zaqarclient/auth/signed_url.py
Normal file
@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2016 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from zaqarclient.auth import base
|
||||
|
||||
|
||||
class SignedURLAuth(base.AuthBackend):
|
||||
"""Authenticate using signature.
|
||||
|
||||
The returned client will only work on one dedicated queue which has been
|
||||
signed.
|
||||
|
||||
:params conf: A dictionary with the signed URL data:
|
||||
- expires
|
||||
- methods
|
||||
- paths
|
||||
- signature
|
||||
- os_project_id
|
||||
:type conf: `dict`
|
||||
"""
|
||||
|
||||
def authenticate(self, api_version, request):
|
||||
"""Set the necessary headers on the request."""
|
||||
request.headers['URL-Expires'] = self.conf['expires']
|
||||
request.headers['URL-Methods'] = ','.join(self.conf['methods'])
|
||||
request.headers['URL-Paths'] = ','.join(self.conf['paths'])
|
||||
request.headers['URL-Signature'] = self.conf['signature']
|
||||
return request
|
@ -42,6 +42,8 @@ class Client(object):
|
||||
:type options: `dict`
|
||||
"""
|
||||
|
||||
queues_module = queues
|
||||
|
||||
def __init__(self, url=None, version=1, conf=None):
|
||||
self.conf = conf or {}
|
||||
|
||||
@ -96,7 +98,7 @@ class Client(object):
|
||||
:returns: A queue instance
|
||||
:rtype: `queues.Queue`
|
||||
"""
|
||||
return queues.Queue(self, ref, **kwargs)
|
||||
return self.queues_module.Queue(self, ref, **kwargs)
|
||||
|
||||
def queues(self, **params):
|
||||
"""Gets a list of queues from the server
|
||||
@ -111,7 +113,7 @@ class Client(object):
|
||||
return iterator._Iterator(self,
|
||||
queue_list,
|
||||
'queues',
|
||||
queues.create_object(self))
|
||||
self.queues_modules.create_object(self))
|
||||
|
||||
def follow(self, ref):
|
||||
"""Follows ref.
|
||||
|
@ -23,6 +23,8 @@ from zaqarclient.queues.v1 import message
|
||||
|
||||
class Queue(object):
|
||||
|
||||
message_module = message
|
||||
|
||||
def __init__(self, client, name, auto_create=True, force_create=False):
|
||||
"""Initialize queue object
|
||||
|
||||
@ -153,7 +155,7 @@ class Queue(object):
|
||||
req, trans = self.client._request_and_transport()
|
||||
msg = core.message_get(trans, req, self._name,
|
||||
message_id)
|
||||
return message.Message(self, **msg)
|
||||
return self.message_module.Message(self, **msg)
|
||||
|
||||
def messages(self, *messages, **params):
|
||||
"""Gets a list of messages from the server
|
||||
@ -195,7 +197,7 @@ class Queue(object):
|
||||
return iterator._Iterator(self.client,
|
||||
msgs,
|
||||
'messages',
|
||||
message.create_object(self))
|
||||
self.message_module.create_object(self))
|
||||
|
||||
def delete_messages(self, *messages):
|
||||
"""Deletes a set of messages from the server
|
||||
@ -223,7 +225,7 @@ class Queue(object):
|
||||
return iterator._Iterator(self.client,
|
||||
msgs,
|
||||
'messages',
|
||||
message.create_object(self))
|
||||
self.message_module.create_object(self))
|
||||
|
||||
def claim(self, id=None, ttl=None, grace=None,
|
||||
limit=None):
|
||||
|
@ -19,6 +19,7 @@ from zaqarclient.common import decorators
|
||||
from zaqarclient.queues.v1 import client
|
||||
from zaqarclient.queues.v1 import iterator
|
||||
from zaqarclient.queues.v2 import core
|
||||
from zaqarclient.queues.v2 import queues
|
||||
from zaqarclient.queues.v2 import subscription
|
||||
|
||||
|
||||
@ -38,6 +39,8 @@ class Client(client.Client):
|
||||
:type options: `dict`
|
||||
"""
|
||||
|
||||
queues_module = queues
|
||||
|
||||
def __init__(self, url=None, version=2, conf=None):
|
||||
self.conf = conf or {}
|
||||
|
||||
|
@ -43,6 +43,7 @@ queue_set_metadata = core.queue_set_metadata
|
||||
queue_get_stats = core.queue_get_stats
|
||||
queue_delete = core.queue_delete
|
||||
queue_list = core.queue_list
|
||||
message_get = core.message_get
|
||||
message_list = core.message_list
|
||||
message_post = core.message_post
|
||||
message_delete = core.message_delete
|
||||
|
@ -13,7 +13,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from zaqarclient import errors
|
||||
from zaqarclient.queues.v1 import queues
|
||||
from zaqarclient.queues.v2 import core
|
||||
from zaqarclient.queues.v2 import message
|
||||
@ -21,19 +20,13 @@ from zaqarclient.queues.v2 import message
|
||||
|
||||
class Queue(queues.Queue):
|
||||
|
||||
def message(self, message_id):
|
||||
"""Gets a message by id
|
||||
message_module = message
|
||||
|
||||
:param message_id: Message's reference
|
||||
:type message_id: `six.text_type`
|
||||
|
||||
:returns: A message
|
||||
:rtype: `dict`
|
||||
"""
|
||||
def signed_url(self, paths=None, ttl_seconds=None, methods=None):
|
||||
req, trans = self.client._request_and_transport()
|
||||
if self.client.api_version >= 2:
|
||||
raise errors.InvalidOperation("Unavailable on versions >= 2")
|
||||
else:
|
||||
msg = core.message_get(trans, req, self._name,
|
||||
message_id)
|
||||
return message.Message(self, **msg)
|
||||
return core.signed_url_create(trans, req, self._name, paths=paths,
|
||||
ttl_seconds=ttl_seconds, methods=methods)
|
||||
|
||||
|
||||
def create_object(parent):
|
||||
return lambda args: Queue(parent, args["name"], auto_create=False)
|
||||
|
@ -75,7 +75,7 @@ class TestBase(testtools.TestCase):
|
||||
def _setup_auth_params(self):
|
||||
self.creds = self._credentials().get_auth_args()
|
||||
|
||||
# FIXME(flwang): Now we're hardcode the keystone auth versioin, since
|
||||
# FIXME(flwang): Now we're hardcode the keystone auth version, since
|
||||
# there is a 'bug' with the osc-config which is returning the auth_url
|
||||
# without version. This should be fixed as long as the bug is fixed.
|
||||
parsed_url = urllib_parse.urlparse(self.creds['auth_url'])
|
||||
|
@ -17,6 +17,7 @@ import json
|
||||
import mock
|
||||
|
||||
from zaqarclient import errors
|
||||
from zaqarclient.queues import client
|
||||
from zaqarclient.queues.v1 import iterator
|
||||
from zaqarclient.queues.v1 import message
|
||||
from zaqarclient.tests.queues import base
|
||||
@ -468,4 +469,24 @@ class QueuesV2QueueUnitTest(QueuesV1_1QueueUnitTest):
|
||||
|
||||
|
||||
class QueuesV2QueueFunctionalTest(QueuesV1_1QueueFunctionalTest):
|
||||
pass
|
||||
|
||||
def test_signed_url(self):
|
||||
queue = self.client.queue('test_queue')
|
||||
messages = [{'ttl': 300, 'body': 'Post It!'}]
|
||||
queue.post(messages)
|
||||
self.addCleanup(queue.delete)
|
||||
signature = queue.signed_url()
|
||||
opts = {
|
||||
'paths': signature['paths'],
|
||||
'expires': signature['expires'],
|
||||
'methods': signature['methods'],
|
||||
'signature': signature['signature'],
|
||||
'os_project_id': signature['project'],
|
||||
}
|
||||
auth_opts = {'backend': 'signed-url',
|
||||
'options': opts}
|
||||
conf = {'auth_opts': auth_opts}
|
||||
signed_client = client.Client(self.url, self.version, conf)
|
||||
queue = signed_client.queue('test_queue')
|
||||
[message] = list(queue.messages())
|
||||
self.assertEqual('Post It!', message.body)
|
||||
|
Loading…
Reference in New Issue
Block a user