Merge "Fix http 500 when getting secret payload with no Acccept header"

This commit is contained in:
Jenkins 2016-02-22 21:44:39 +00:00 committed by Gerrit Code Review
commit c06fb13ff9
5 changed files with 72 additions and 19 deletions

View File

@ -111,10 +111,15 @@ def store_secret(unencrypted_raw, content_type_raw, content_encoding,
def get_secret(requesting_content_type, secret_model, project_model,
twsk=None, transport_key=None):
tr.analyze_before_decryption(requesting_content_type)
secret_metadata = _get_secret_meta(secret_model)
# NOTE: */* is the pecan default meaning no content type sent in. In this
# case we should use the mime type stored in the metadata.
if requesting_content_type == '*/*':
requesting_content_type = secret_metadata['content_type']
tr.analyze_before_decryption(requesting_content_type)
if twsk is not None:
secret_metadata['trans_wrapped_session_key'] = twsk
secret_metadata['transport_key'] = transport_key

View File

@ -280,6 +280,23 @@ class WhenGettingPuttingOrDeletingSecret(utils.BarbicanAPIBaseTestCase):
self.assertEqual(200, get_resp.status_int)
self.assertEqual(payload, get_resp.body)
def test_get_secret_payload_with_pecan_default_accept_header(self):
payload = 'a very interesting string'
resp, secret_uuid = create_secret(
self.app,
payload=payload,
content_type='text/plain'
)
self.assertEqual(201, resp.status_int)
headers = {'Accept': '*/*'}
get_resp = self.app.get(
'/secrets/{0}/payload'.format(secret_uuid), headers=headers
)
self.assertEqual(200, get_resp.status_int)
self.assertEqual(payload, get_resp.body)
def test_get_secret_payload_with_blank_accept_header(self):
payload = 'a very interesting string'
resp, secret_uuid = create_secret(

View File

@ -19,11 +19,13 @@ from functionaltests.api.v1.models import secret_models
class SecretBehaviors(base_behaviors.BaseBehaviors):
def create_secret(self, model, headers=None, use_auth=True,
user_name=None, admin=None):
def create_secret(self, model, extra_headers=None, omit_headers=None,
use_auth=True, user_name=None, admin=None):
"""Create a secret from the data in the model.
:param model: The metadata used to create the secret
:param extra_headers: Optional HTTP headers to add to the request
:param omit_headers: headers to delete before making the request
:param use_auth: Boolean for whether to send authentication headers
:param user_name: The user name used to create the secret
:param admin: The user with permissions to delete the secrets
@ -32,7 +34,8 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
"""
resp = self.client.post('secrets', request_model=model,
extra_headers=headers, use_auth=use_auth,
extra_headers=extra_headers,
omit_headers=omit_headers, use_auth=use_auth,
user_name=user_name)
# handle expected JSON parsing errors for unauthenticated requests
@ -49,8 +52,8 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
def update_secret_payload(self, secret_ref, payload, payload_content_type,
payload_content_encoding=None,
extra_headers=None, use_auth=True,
user_name=None):
extra_headers=None, omit_headers=None,
use_auth=True, user_name=None):
"""Updates a secret's payload data.
:param secret_ref: HATEOAS ref of the secret to be updated
@ -58,6 +61,7 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
:param payload_content_type: value for the Content-Type header
:param payload_content_encoding: value for the Content-Encoding header
:param extra_headers: Optional HTTP headers to add to the request
:param omit_headers: headers to delete before making the request
:param use_auth: Boolean for whether to send authentication headers
:param user_name: The user name used to update the secret
:return: the response from the PUT update
@ -73,11 +77,12 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
headers.update(extra_headers)
return self.client.put(secret_ref, data=payload, extra_headers=headers,
omit_headers=omit_headers,
use_auth=use_auth, user_name=user_name)
def get_secret(self, secret_ref, payload_content_type,
payload_content_encoding=None, extra_headers=None,
use_auth=True, user_name=None):
omit_headers=None, use_auth=True, user_name=None):
headers = {'Accept': payload_content_type,
'Accept-Encoding': payload_content_encoding}
@ -86,12 +91,15 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
headers.update(extra_headers)
return self.client.get(secret_ref + '/payload',
extra_headers=headers, use_auth=use_auth,
extra_headers=headers,
omit_headers=omit_headers, use_auth=use_auth,
user_name=user_name)
def get_secret_based_on_content_type(self, secret_ref,
payload_content_type,
payload_content_encoding=None,
extra_headers=None,
omit_headers=None,
user_name=None):
"""Retrieves a secret's payload based on the content type
@ -101,23 +109,31 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
headers = {'Accept': payload_content_type,
'Accept-Encoding': payload_content_encoding}
return self.client.get(secret_ref, extra_headers=headers,
user_name=user_name)
if extra_headers:
headers.update(extra_headers)
def get_secret_metadata(self, secret_ref, use_auth=True, user_name=None):
return self.client.get(secret_ref, extra_headers=headers,
omit_headers=omit_headers, user_name=user_name)
def get_secret_metadata(self, secret_ref, extra_headers=None,
omit_headers=None, use_auth=True, user_name=None):
"""Retrieves a secret's metadata.
:param secret_ref: HATEOAS ref of the secret to be retrieved
:param extra_headers: Optional HTTP headers to add to the request
:param omit_headers: headers to delete before making the request
:param use_auth: Boolean for whether to send authentication headers
:param user_name: The user name used to get the metadata
:return: A request response object
"""
return self.client.get(
secret_ref, response_model_type=secret_models.SecretModel,
secret_ref, extra_headers=extra_headers, omit_headers=omit_headers,
response_model_type=secret_models.SecretModel,
use_auth=use_auth, user_name=user_name)
def get_secrets(self, limit=10, offset=0, filter=None,
extra_headers=None, use_auth=True, user_name=None):
extra_headers=None, omit_headers=None, use_auth=True,
user_name=None):
"""Handles getting a list of secrets.
:param limit: limits number of returned secrets
@ -126,6 +142,7 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
:param filter: optional filter to limit the returned secrets to
those whose name matches the filter.
:param extra_headers: Optional HTTP headers to add to the request
:param omit_headers: headers to delete before making the request
:param use_auth: Boolean for whether to send authentication headers
:param user_name: The user name used to list the secrets
"""
@ -134,6 +151,7 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
params['name'] = filter
resp = self.client.get('secrets', params=params,
extra_headers=extra_headers,
omit_headers=omit_headers,
use_auth=use_auth, user_name=user_name)
# handle expected JSON parsing errors for unauthenticated requests
@ -147,18 +165,20 @@ class SecretBehaviors(base_behaviors.BaseBehaviors):
return resp, secrets, next_ref, prev_ref
def delete_secret(self, secret_ref, extra_headers=None,
def delete_secret(self, secret_ref, extra_headers=None, omit_headers=None,
expected_fail=False, use_auth=True, user_name=None):
"""Delete a secret.
:param secret_ref: HATEOAS ref of the secret to be deleted
:param extra_headers: Optional HTTP headers to add to the request
:param omit_headers: headers to delete before making the request
:param expected_fail: If test is expected to fail the deletion
:param use_auth: Boolean for whether to send authentication headers
:param user_name: The user name used to delete the secret
:return A request response object
"""
resp = self.client.delete(secret_ref, extra_headers=extra_headers,
omit_headers=omit_headers,
use_auth=use_auth, user_name=user_name)
if not expected_fail:

View File

@ -195,7 +195,8 @@ class SecretsTestCase(base.TestCase):
get_resp = self.behaviors.get_secret(
secret_ref,
payload_content_type='')
payload_content_type='',
omit_headers=['Accept'])
self.assertEqual(get_resp.status_code, 200)
self.assertIn(test_model.payload,
binascii.b2a_base64(get_resp.content))
@ -928,7 +929,7 @@ class SecretsTestCase(base.TestCase):
changed_host_header = {'Host': malicious_hostname}
resp, secret_ref = self.behaviors.create_secret(
test_model, headers=changed_host_header)
test_model, extra_headers=changed_host_header)
self.assertEqual(resp.status_code, 201)
@ -1108,7 +1109,7 @@ class SecretsUnauthedTestCase(base.TestCase):
model = secret_models.SecretModel(self.default_secret_create_data)
resp, secret_ref = self.behaviors.create_secret(
model, headers=self.dummy_project_id_header, use_auth=False
model, extra_headers=self.dummy_project_id_header, use_auth=False
)
self.assertEqual(401, resp.status_code)
@ -1122,7 +1123,7 @@ class SecretsUnauthedTestCase(base.TestCase):
model = secret_models.SecretModel(self.default_secret_create_data)
resp, secret_ref = self.behaviors.create_secret(
model, headers=self.project_id_header, use_auth=False
model, extra_headers=self.project_id_header, use_auth=False
)
self.assertEqual(401, resp.status_code)

View File

@ -235,6 +235,7 @@ class BarbicanClient(object):
return models, next_ref, prev_ref
def request(self, method, url, data=None, extra_headers=None,
omit_headers=None,
use_auth=True, response_model_type=None, request_model=None,
params=None, user_name=None):
"""Prepares and sends http request through Requests."""
@ -247,6 +248,15 @@ class BarbicanClient(object):
if extra_headers:
headers.update(extra_headers)
if omit_headers:
for header in omit_headers:
try:
del headers[header]
except KeyError:
# key error means we tried to delete a nonexistent
# entry - we don't care about that
pass
# Attempt to serialize model if required
if request_model:
data = self.attempt_to_serialize(request_model)