def is_valid_analytics_request(request): default_end_time = datetime.datetime.utcnow() default_start_time = (datetime.datetime.utcnow() - datetime.timedelta(days=1)) domain = request.GET.get('domain', "") startTime = request.GET.get( 'startTime', default_start_time.strftime("%Y-%m-%dT%H:%M:%S")) endTime = request.GET.get('endTime', default_end_time.strftime("%Y-%m-%dT%H:%M:%S")) # NOTE(TheSriram): metricType is a required entity metricType = request.GET.get('metricType', None) if not is_valid_domain_name(domain): raise exceptions.ValidationFailed("domain %s is not valid." % domain) try: start_time = datetime.datetime.strptime(startTime, "%Y-%m-%dT%H:%M:%S") end_time = datetime.datetime.strptime(endTime, "%Y-%m-%dT%H:%M:%S") except Exception as e: raise exceptions.ValidationFailed('startTime or endTime is not in ' 'valid format. details: %s.' 'Valid time stamp format is: ' 'YYYY-mm-ddTHH:MM:SS' % str(e)) else: if start_time > end_time: raise exceptions.ValidationFailed('startTime cannot be later than' ' endTime') # NOTE(TheSriram): The metrics listed below are the currently supported # metric types valid_metric_types = [ 'requestCount', 'bandwidthOut', 'httpResponseCode_1XX', 'httpResponseCode_2XX', 'httpResponseCode_3XX', 'httpResponseCode_4XX', 'httpResponseCode_5XX' ] if metricType not in valid_metric_types: raise exceptions.ValidationFailed('Must provide an metric name....' 'Valid metric types are: %s' % valid_metric_types) # Update context so the decorated function can get all this parameters request.context.call_args = { 'domain': domain, 'startTime': start_time, 'endTime': end_time, 'metricType': metricType }
def wrapper(value, **kwargs): if none_ok and value is None: return if not none_ok and value is None: msg = 'None value not permitted' raise exceptions.ValidationFailed(msg) if empty_ok and value == '': return if not empty_ok and value == '': msg = 'Empty value not permitted' raise exceptions.ValidationFailed(msg) func(value)
def json_matches_flavor_schema_inner(request, schema=None): try: data = json.loads(request.body.decode('utf-8')) except ValueError: raise exceptions.ValidationFailed('Invalid JSON string') is_valid_flavor_configuration(data, schema)
def json_matches_schema_inner(request, schema=None): errors_list = [] try: data = json.loads(request.body.decode('utf-8')) except ValueError: raise exceptions.ValidationFailed('Invalid JSON string') if schema is not None: errors_list = list( jsonschema.Draft3Validator(schema).iter_errors(data)) if len(errors_list) > 0: details = dict(errors=[{ 'message': str(getattr(error, "message", error)) } for error in errors_list]) raise exceptions.ValidationFailed(json.dumps(details)) else: return
def is_valid_json(r): """Test for a valid JSON string.""" if len(r.body) == 0: return else: try: json.loads(r.body.decode('utf-8')) except Exception as e: e raise exceptions.ValidationFailed('Invalid JSON string') else: return
def is_valid_provider_url(request): provider_url = request.GET.get("provider_url", None) if not provider_url: raise exceptions.ValidationFailed('provider_url needs to be ' 'provided as a query parameter') provider_url_regex_1 = ('^([A-Za-z0-9-]){1,255}\.([A-Za-z0-9-]){1,255}\.' '([A-Za-z0-9-]){1,255}\.([A-Za-z0-9-]){1,255}\.' '([A-Za-z0-9-]){1,255}\.([A-Za-z0-9-]){1,255}$') provider_url_regex_2 = ('^([A-Za-z0-9-]){1,255}\.([A-Za-z0-9-]){1,255}\.' '([A-Za-z0-9-]){1,255}\.([A-Za-z0-9-]){1,255}\.' '([A-Za-z0-9-]){1,255}$') if not re.match(provider_url_regex_1, provider_url): if not re.match(provider_url_regex_2, provider_url): raise exceptions.ValidationFailed( u'Provider url {0} is not valid'.format(provider_url)) # Update context so the decorated function can get all this parameters request.context.call_args = { 'provider_url': provider_url, }
def is_valid_domain_by_name(domain_name): domain_regex = ('^((?=[a-z0-9-]{1,63}\.)[a-z0-9]+' '(-[a-z0-9]+)*\.)+[a-z]{2,63}$') # allow Punycode # domain_regex = ('^((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+' # '(-[a-z0-9]+)*\.)+[a-z]{2,63}$') # shared ssl domain shared_ssl_domain_regex = '^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]?$' if len(domain_name) > 253: raise exceptions.ValidationFailed( u'Domain {0} is too long'.format(domain_name)) if len(domain_name) < 3: raise exceptions.ValidationFailed( u'Domain {0} is too short'.format(domain_name)) if not re.match(domain_regex, domain_name): if not re.match(shared_ssl_domain_regex, domain_name): raise exceptions.ValidationFailed( u'Domain {0} is not valid'.format(domain_name))
def is_valid_json(r): """Simple validation function for testing purposes that ensures that input is a valid json string """ if len(r.body) == 0: return else: try: json.loads(r.body.decode('utf-8')) except Exception as e: e raise exceptions.ValidationFailed('Invalid JSON string') else: return
def is_valid_flavor_configuration(flavor, schema): if schema is not None: errors_list = list( jsonschema.Draft3Validator(schema).iter_errors(flavor)) if len(errors_list) > 0: details = dict(errors=[{ 'message': '-'.join([ "[%s]" % "][".join(repr(p) for p in error.path), str(getattr(error, "message", error)) ]) } for error in errors_list]) raise exceptions.ValidationFailed(json.dumps(details)) return
def is_valid_certificate_status(request): status = request.GET.get('status', "") # NOTE(TheSriram): The statuses listed below are the currently # supported statuses VALID_CERT_STATUSES = [ u'create_in_progress', u'deployed', u'failed', u'cancelled' ] if status not in VALID_CERT_STATUSES: raise exceptions.ValidationFailed('Unknown status type {0} present, ' 'Valid status types ' 'are: ' '{1}'.format(status, VALID_CERT_STATUSES)) # Update context so the decorated function can get all this parameters request.context.call_args = {'status': status}
def is_valid_domain_by_name_or_akamai_setting(query): valid_domain = True domain_exc = None valid_setting = True setting_exc = None try: is_valid_domain_by_name(query) except Exception as exc: valid_domain = False domain_exc = exc try: is_valid_akamai_setting(query) except Exception as exc: valid_setting = False setting_exc = exc if valid_domain is False and valid_setting is False: raise exceptions.ValidationFailed(str(domain_exc) + str(setting_exc))
def with_schema_falcon(request, schema=None): """Use to decorate a falcon style controller route :param request: A falcon request :param schema: a Json schema to validate against """ validation_failed = False v_error = None if schema is not None: errors_list = [] try: data = json.loads(request.body) errors_list = list( jsonschema.Draft3Validator(schema).iter_errors(data)) except ValueError: validation_failed = True v_error = ["Invalid JSON body in request"] if len(errors_list) > 0: validation_failed = True v_error = errors_list if validation_failed: raise exceptions.ValidationFailed(repr(v_error))
def is_request(candidate): if not isinstance(candidate, DummyRequest): raise exceptions.ValidationFailed('Input must be a request')
def is_valid_akamai_setting(setting): if setting not in ['san_cert_hostname_limit']: raise exceptions.ValidationFailed( 'Invalid akamai setting : {0}'.format(setting))
def is_valid_project_id(project_id): project_id_regex = '^[a-zA-Z0-9_\\-\\.]{1,256}$' if not re.match(project_id_regex, project_id): raise exceptions.ValidationFailed('Invalid ' 'project_id : ' '{0}'.format(project_id))
def req_accepts_json_pecan(request, desired_content_type='application/json'): # Assume the transport is pecan for now # for falcon the syntax should actually be: # request.accept('application/json') if not request.accept(desired_content_type): raise exceptions.ValidationFailed('Invalid Accept Header')
def is_valid_service_configuration(service, schema): if schema is not None: errors_list = list( jsonschema.Draft3Validator(schema).iter_errors(service)) if len(errors_list) > 0: details = dict(errors=[{ 'message': '-'.join([ "[%s]" % "][".join(repr(p) for p in error.path), str(getattr(error, "message", error)) ]) } for error in errors_list]) raise exceptions.ValidationFailed(json.dumps(details)) # Schema structure is valid. Check the functional rules. # 1. origins and origin rules must be unique if 'origins' in service: origin_rules = [] origins = [] for origin in service['origins']: origin_ssl = 'https' if origin.get('ssl') else 'http' origin_value = u"{0}://{1}".format(origin_ssl, origin.get('origin')) if origin_value in origins: raise exceptions.ValidationFailed( 'The origin {0} already exists for another ' 'origin on this service'.format(origin_value)) else: origins.append(origin_value) if 'rules' in origin: for rule in origin['rules']: request_url = rule['request_url'] if not request_url.startswith('/'): request_url = ('/' + request_url) if request_url in origin_rules: raise exceptions.ValidationFailed( 'The path {0} already exists for another ' 'origin on this service'.format(request_url)) else: origin_rules.append(request_url) # 2. caching rules must be unique if 'caching' in service: caching_rules = [] for caching in service['caching']: if 'rules' in caching: for rule in caching['rules']: request_url = rule['request_url'] if request_url in caching_rules: raise exceptions.ValidationFailed( 'The path {0} already exists for another ' 'caching rule on this service'.format(request_url)) else: caching_rules.append(request_url) # 3. domains must be unique if 'domains' in service: domains = [] for domain in service['domains']: domain_value = u"{0}://{1}".format(domain.get('protocol', 'http'), domain.get('domain')) if domain_value in domains: raise exceptions.ValidationFailed( 'The domain {0} already exists on another service'.format( domain_value)) else: domains.append(domain_value) # We allow multiple restrictions rules on the same path # 5. domains must be valid if 'domains' in service: for domain in service['domains']: if not is_valid_domain(domain): raise exceptions.ValidationFailed( u'Domain {0} is not a valid domain'.format( domain.get('domain'))) # 6. origins and domains cannot be the same if 'origins' in service and 'domains' in service: origins = set() for origin in service['origins']: origin_name = origin.get('origin').lower().strip() origins.add(origin_name) domains = set() for domain in service['domains']: domain_name = domain.get('domain').lower().strip() domains.add(domain_name) if origins.intersection(domains): raise exceptions.ValidationFailed( u'Domains and origins cannot be same: {0}'.format(origin)) # 7. origins must be valid if 'origins' in service: for origin in service['origins']: if not is_valid_origin(origin): raise exceptions.ValidationFailed( u'Origin {0} is not valid'.format(origin.get('origin'))) # 8. domains must not be root domains if 'domains' in service: for domain in service['domains']: protocol = domain.get('protocol', 'http') certificate = domain.get('certificate') # for a shared SSL domains, domain name is a single segment # so, root domain validation does not apply to it if protocol == "https" and certificate == "shared": continue if is_root_domain(domain): raise exceptions.ValidationFailed( u'{0} is a root domain. Most DNS providers do not allow ' 'setting a CNAME on a root domain. Please add a subdomain ' '(e.g. www.{0})'.format(domain.get('domain'))) # 9. Hostheadervalue must be valid if 'origins' in service: for origin in service['origins']: if 'hostheadervalue' in origin: hostheadervalue = origin.get('hostheadervalue') if hostheadervalue is not None: if not is_valid_domain_name(hostheadervalue): raise exceptions.ValidationFailed( u'The host header {0} is not valid'.format( hostheadervalue)) # 10. Need to validate restriction correctness here # Cannot allow one restriction rule entity to have both # "blacklist" and "whitelist" restriction type whitelist_restriction_entities = {} blacklist_restriction_entities = {} if 'restrictions' in service: for restriction in service['restrictions']: if restriction.get('access', 'blacklist') == 'blacklist': for rule in restriction['rules']: entity = None request_url = '/*' for key in rule: if key == 'name': pass elif key == 'request_url': request_url = rule['request_url'] else: entity = key # validate country code is valid # if key == 'geography': # rule[key] is valid if request_url not in blacklist_restriction_entities: blacklist_restriction_entities[request_url] = [] blacklist_restriction_entities[request_url].append(entity) elif restriction.get('access', 'whitelist') == 'whitelist': for rule in restriction['rules']: entity = None request_url = '/*' for key in rule: if key == 'name': pass elif key == 'request_url': request_url = rule['request_url'] else: entity = key # validate country code is valid # if key == 'geography': # rule[key] is valid if request_url in blacklist_restriction_entities and \ entity in blacklist_restriction_entities[ request_url]: raise exceptions.ValidationFailed( 'Cannot blacklist and whitelist [%s] on %s' ' at the same time' % key, request_url) if request_url not in whitelist_restriction_entities: whitelist_restriction_entities[request_url] = [] whitelist_restriction_entities[request_url].append(entity) for request_url in whitelist_restriction_entities: if request_url in blacklist_restriction_entities: intersect_entities = set( blacklist_restriction_entities[request_url] ).intersection(whitelist_restriction_entities[request_url]) if len(intersect_entities) > 0: raise exceptions.ValidationFailed( 'Cannot blacklist and whitelist %s on %s' ' at the same time' % (str(list(intersect_entities)), request_url)) # referrer domains must be valid for rule in restriction['rules']: if rule.get("referrer"): referrer = rule.get("referrer") if not is_valid_domain_name(referrer): raise exceptions.ValidationFailed( u'Referrer {0} is not a valid domain'.format( referrer)) return
def is_upper(z): """Ensures Uppercase.""" if z.upper() != z: raise exceptions.ValidationFailed('{0} no uppercase'.format(z))
def is_valid_service_id(service_id): try: uuid.UUID(service_id) except ValueError: raise exceptions.ValidationFailed('Invalid service id')
def is_response(candidate): if not isinstance(candidate, DummyResponse): raise exceptions.ValidationFailed('Input must be a response')
def is_upper(z): """Simple validation function for testing purposes that ensures that input is all caps """ if z.upper() != z: raise exceptions.ValidationFailed('{0} no uppercase'.format(z))