Validating uuids on api calls

This commit is contained in:
Andrew Melton 2013-02-26 16:42:32 -05:00
parent 07dcb5685a
commit adc7693eeb
7 changed files with 214 additions and 20 deletions

@ -103,7 +103,11 @@ def _check_has_field(klass, field_name):
def _get_filter_args(klass, request):
filter_args = {}
if 'instance' in request.GET:
filter_args['instance'] = request.GET['instance']
uuid = request.GET['instance']
filter_args['instance'] = uuid
if not utils.is_uuid_like(uuid):
msg = "%s is not uuid-like" % uuid
raise BadRequestException(msg)
for (key, value) in request.GET.items():

@ -8,7 +8,7 @@ from django.shortcuts import get_object_or_404
import datetime_to_decimal as dt
import models
import views
import utils
SECS_PER_HOUR = 60 * 60
SECS_PER_DAY = SECS_PER_HOUR * 24
@ -76,6 +76,11 @@ def rsp(data, status=200):
status=status)
def error_response(status, type, message):
results = [["Error", "Message"], [type, message]]
return rsp(results, status)
def do_deployments(request):
deployments = get_deployments()
results = [["#", "Name"]]
@ -102,6 +107,10 @@ def do_hosts(request):
def do_uuid(request):
uuid = str(request.GET['uuid'])
if not utils.is_uuid_like(uuid):
msg = "%s is not uuid-like" % uuid
return error_response(400, 'Bad Request', msg)
related = models.RawData.objects.select_related().filter(instance=uuid)\
.order_by('when')
results = [["#", "?", "When", "Deployment", "Event", "Host", "State",
@ -116,6 +125,10 @@ def do_uuid(request):
def do_timings_uuid(request):
uuid = request.GET['uuid']
if not utils.is_uuid_like(uuid):
msg = "%s is not uuid-like" % uuid
return error_response(400, 'Bad Request', msg)
return rsp(get_timings_for_uuid(uuid))
@ -167,6 +180,10 @@ def do_summary(request):
def do_request(request):
request_id = request.GET['request_id']
if not utils.is_request_id_like(request_id):
msg = "%s is not request-id-like" % request_id
return error_response(400, 'Bad Request', msg)
events = models.RawData.objects.filter(request_id=request_id) \
.order_by('when')
results = [["#", "?", "When", "Deployment", "Event", "Host",
@ -270,10 +287,8 @@ def do_watch(request, deployment_id):
def do_kpi(request, tenant_id=None):
if tenant_id:
if models.RawData.objects.filter(tenant=tenant_id).count() == 0:
results = [["Error", "Message"]]
message = "Could not find raws for tenant %s" % tenant_id
results.append(["NotFound", message])
return rsp(results, 404)
return error_response(404, 'Not Found', message)
yesterday = datetime.datetime.utcnow() - datetime.timedelta(days=1)
yesterday = dt.dt_to_decimal(yesterday)
@ -297,7 +312,11 @@ def do_list_usage_launches(request):
filter_args = {}
if 'instance' in request.GET:
filter_args['instance'] = request.GET['instance']
uuid = request.GET['instance']
if not utils.is_uuid_like(uuid):
msg = "%s is not uuid-like" % uuid
return error_response(400, 'Bad Request', msg)
filter_args['instance'] = uuid
if len(filter_args) > 0:
launches = models.InstanceUsage.objects.filter(**filter_args)
@ -319,7 +338,11 @@ def do_list_usage_deletes(request):
filter_args = {}
if 'instance' in request.GET:
filter_args['instance'] = request.GET['instance']
uuid = request.GET['instance']
if not utils.is_uuid_like(uuid):
msg = "%s is not uuid-like" % uuid
return error_response(400, 'Bad Request', msg)
filter_args['instance'] = uuid
if len(filter_args) > 0:
deletes = models.InstanceDeletes.objects.filter(**filter_args)
@ -344,7 +367,11 @@ def do_list_usage_exists(request):
filter_args = {}
if 'instance' in request.GET:
filter_args['instance'] = request.GET['instance']
uuid = request.GET['instance']
if not utils.is_uuid_like(uuid):
msg = "%s is not uuid-like" % uuid
return error_response(400, 'Bad Request', msg)
filter_args['instance'] = uuid
if len(filter_args) > 0:
exists = models.InstanceExists.objects.filter(**filter_args)

@ -1,7 +1,9 @@
import datetime
import uuid
from stacktach import datetime_to_decimal as dt
def str_time_to_unix(when):
if 'T' in when:
try:
@ -23,3 +25,19 @@ def str_time_to_unix(when):
print "BAD DATE: ", e
return dt.dt_to_decimal(when)
def is_uuid_like(val):
try:
converted = str(uuid.UUID(val))
if '-' not in val:
converted = converted.replace('-', '')
return converted == val
except (TypeError, ValueError, AttributeError):
return False
def is_request_id_like(val):
if val[0:4] == 'req-':
val = val[4:]
return is_uuid_like(val)

@ -47,6 +47,17 @@ class DBAPITestCase(unittest.TestCase):
self.assertEquals(filter_args.get('launched_at__lte'),
end_decimal)
def test_get_filter_args_bad_uuid(self):
fake_model = self.make_fake_model()
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'instance': 'obviouslybaduuid'}
self.mox.ReplayAll()
self.assertRaises(dbapi.BadRequestException, dbapi._get_filter_args,
fake_model, fake_request)
self.mox.VerifyAll()
def test_get_filter_args_bad_min_value(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'launched_at_min': 'obviouslybaddatetime'}

@ -1 +1,44 @@
__author__ = 'andrewmelton'
import unittest
import mox
from stacktach import utils as stacktach_utils
from utils import INSTANCE_ID_1
from utils import MESSAGE_ID_1
from utils import REQUEST_ID_1
class StacktachUtilsTestCase(unittest.TestCase):
def setUp(self):
self.mox = mox.Mox()
def tearDown(self):
self.mox.UnsetStubs()
def test_is_uuid_like(self):
uuid = INSTANCE_ID_1
self.assertTrue(stacktach_utils.is_uuid_like(uuid))
def test_is_uuid_like_no_dashes(self):
uuid = "08f685d963524dbc827196cc54bf14cd"
self.assertTrue(stacktach_utils.is_uuid_like(uuid))
def test_is_uuid_like_invalid(self):
uuid = "$-^&#$"
self.assertFalse(stacktach_utils.is_uuid_like(uuid))
def test_is_request_id_like_with_uuid(self):
uuid = MESSAGE_ID_1
self.assertTrue(stacktach_utils.is_request_id_like(uuid))
def test_is_message_id_like_with_req_uuid(self):
uuid = REQUEST_ID_1
self.assertTrue(stacktach_utils.is_request_id_like(uuid))
def test_is_message_id_like_invalid_req(self):
uuid = "req-$-^&#$"
self.assertFalse(stacktach_utils.is_request_id_like(uuid))
def test_is_message_id_like_invalid(self):
uuid = "$-^&#$"
self.assertFalse(stacktach_utils.is_request_id_like(uuid))

@ -10,6 +10,7 @@ from stacktach import stacky_server
import utils
from utils import INSTANCE_ID_1
from utils import INSTANCE_ID_2
from utils import REQUEST_ID_1
class StackyServerTestCase(unittest.TestCase):
@ -58,7 +59,7 @@ class StackyServerTestCase(unittest.TestCase):
raw.publisher = "api.example.com"
raw.service = 'api'
raw.host = 'example.com'
raw.request_id = 'req-1'
raw.request_id = REQUEST_ID_1
raw.json = '{"key": "value"}'
return raw
@ -250,6 +251,36 @@ class StackyServerTestCase(unittest.TestCase):
self.assertEqual(json_resp[1], body)
self.mox.VerifyAll()
def test_do_uuid_bad_uuid(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'uuid': "obviouslybaduuid"}
self.mox.ReplayAll()
resp = stacky_server.do_uuid(fake_request)
self.assertEqual(resp.status_code, 400)
resp_json = json.loads(resp.content)
self.assertEqual(len(resp_json), 2)
self.assertEqual(resp_json[0], ['Error', 'Message'])
msg = 'obviouslybaduuid is not uuid-like'
self.assertEqual(resp_json[1], ['Bad Request', msg])
self.mox.VerifyAll()
def test_do_timings_uuid_bad_uuid(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'uuid': "obviouslybaduuid"}
self.mox.ReplayAll()
resp = stacky_server.do_timings_uuid(fake_request)
self.assertEqual(resp.status_code, 400)
resp_json = json.loads(resp.content)
self.assertEqual(len(resp_json), 2)
self.assertEqual(resp_json[0], ['Error', 'Message'])
msg = 'obviouslybaduuid is not uuid-like'
self.assertEqual(resp_json[1], ['Bad Request', msg])
self.mox.VerifyAll()
def test_do_timings(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'name': 'test.event'}
@ -314,10 +345,10 @@ class StackyServerTestCase(unittest.TestCase):
def test_do_request(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'request_id': 'req-1'}
fake_request.GET = {'request_id': REQUEST_ID_1}
raw = self._create_raw()
results = self.mox.CreateMockAnything()
models.RawData.objects.filter(request_id='req-1').AndReturn(results)
models.RawData.objects.filter(request_id=REQUEST_ID_1).AndReturn(results)
results.order_by('when').AndReturn(results)
results.__iter__().AndReturn([raw].__iter__())
self.mox.ReplayAll()
@ -341,6 +372,21 @@ class StackyServerTestCase(unittest.TestCase):
self.assertEqual(json_resp[1][8], None)
self.mox.VerifyAll()
def test_do_request_bad_request_id(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'request_id': "obviouslybaduuid"}
self.mox.ReplayAll()
resp = stacky_server.do_request(fake_request)
self.assertEqual(resp.status_code, 400)
resp_json = json.loads(resp.content)
self.assertEqual(len(resp_json), 2)
self.assertEqual(resp_json[0], ['Error', 'Message'])
msg = 'obviouslybaduuid is not request-id-like'
self.assertEqual(resp_json[1], ['Bad Request', msg])
self.mox.VerifyAll()
def _assert_on_show(self, values, raw):
self.assertEqual(len(values), 12)
self.assertEqual(values[0], ["Key", "Value"])
@ -587,7 +633,7 @@ class StackyServerTestCase(unittest.TestCase):
self.assertEqual(len(body), 2)
self.assertEqual(body[0], ['Error', 'Message'])
msg = 'Could not find raws for tenant 55555'
self.assertEqual(body[1], ['NotFound', msg])
self.assertEqual(body[1], ['Not Found', msg])
self.mox.VerifyAll()
@ -642,6 +688,21 @@ class StackyServerTestCase(unittest.TestCase):
self.mox.VerifyAll()
def test_do_list_usage_launches_bad_instance(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'instance': "obviouslybaduuid"}
self.mox.ReplayAll()
resp = stacky_server.do_list_usage_launches(fake_request)
self.assertEqual(resp.status_code, 400)
resp_json = json.loads(resp.content)
self.assertEqual(len(resp_json), 2)
self.assertEqual(resp_json[0], ['Error', 'Message'])
msg = 'obviouslybaduuid is not uuid-like'
self.assertEqual(resp_json[1], ['Bad Request', msg])
self.mox.VerifyAll()
def test_do_list_usage_deletes(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {}
@ -693,6 +754,21 @@ class StackyServerTestCase(unittest.TestCase):
self.assertEqual(resp_json[1][2], str(delete_time_str))
self.mox.VerifyAll()
def test_do_list_usage_deletes_bad_instance(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'instance': "obviouslybaduuid"}
self.mox.ReplayAll()
resp = stacky_server.do_list_usage_deletes(fake_request)
self.assertEqual(resp.status_code, 400)
resp_json = json.loads(resp.content)
self.assertEqual(len(resp_json), 2)
self.assertEqual(resp_json[0], ['Error', 'Message'])
msg = 'obviouslybaduuid is not uuid-like'
self.assertEqual(resp_json[1], ['Bad Request', msg])
self.mox.VerifyAll()
def test_do_list_usage_exists(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {}
@ -752,3 +828,18 @@ class StackyServerTestCase(unittest.TestCase):
self.assertEqual(resp_json[1][2], str(delete_time_str))
self.mox.VerifyAll()
def test_do_list_usage_exists_bad_instance(self):
fake_request = self.mox.CreateMockAnything()
fake_request.GET = {'instance': "obviouslybaduuid"}
self.mox.ReplayAll()
resp = stacky_server.do_list_usage_exists(fake_request)
self.assertEqual(resp.status_code, 400)
resp_json = json.loads(resp.content)
self.assertEqual(len(resp_json), 2)
self.assertEqual(resp_json[0], ['Error', 'Message'])
msg = 'obviouslybaduuid is not uuid-like'
self.assertEqual(resp_json[1], ['Bad Request', msg])
self.mox.VerifyAll()

@ -7,15 +7,15 @@ TENANT_ID_1 = 'testtenantid1'
from stacktach import datetime_to_decimal as dt
INSTANCE_ID_1 = 'testinstanceid1'
INSTANCE_ID_2 = 'testinstanceid2'
INSTANCE_ID_1 = "08f685d9-6352-4dbc-8271-96cc54bf14cd"
INSTANCE_ID_2 = "515adf96-41d3-b86d-5467-e584edc61dab"
MESSAGE_ID_1 = 'testmessageid1'
MESSAGE_ID_2 = 'testmessageid2'
MESSAGE_ID_1 = "7f28f81b-29a2-43f2-9ba1-ccb3e53ab6c8"
MESSAGE_ID_2 = "4d596126-0f04-4329-865f-7b9a7bd69bcf"
REQUEST_ID_1 = 'testrequestid1'
REQUEST_ID_2 = 'testrequestid2'
REQUEST_ID_3 = 'testrequestid3'
REQUEST_ID_1 = 'req-611a4d70-9e47-4b27-a95e-27996cc40c06'
REQUEST_ID_2 = 'req-a951dec0-52ee-425d-9f56-d68bd1ad00ac'
REQUEST_ID_3 = 'req-039a33f7-5849-4406-8166-4db8cd085f52'
def decimal_utc(t = datetime.datetime.utcnow()):