1 |
|
# -*- coding: utf-8 -*- |
2 |
|
|
3 |
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
4 |
|
# you may not use this file except in compliance with the License. |
5 |
|
# You may obtain a copy of the License at |
6 |
|
# |
7 |
|
# http://www.apache.org/licenses/LICENSE-2.0 |
8 |
|
# |
9 |
|
# Unless required by applicable law or agreed to in writing, software |
10 |
|
# distributed under the License is distributed on an "AS IS" BASIS, |
11 |
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
12 |
|
# implied. |
13 |
|
# See the License for the specific language governing permissions and |
14 |
|
# limitations under the License. |
15 |
|
|
16 |
1 |
from http import HTTPStatus |
17 |
|
|
18 |
1 |
from jsonschema import exceptions as js_e, validate as js_v |
19 |
|
|
20 |
1 |
__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>" |
21 |
1 |
__version__ = "0.1" |
22 |
1 |
version_date = "Jun 2020" |
23 |
|
|
24 |
|
""" |
25 |
|
Validator of input data using JSON schemas |
26 |
|
""" |
27 |
|
|
28 |
|
# Basis schemas |
29 |
1 |
name_schema = { |
30 |
|
"type": "string", |
31 |
|
"minLength": 1, |
32 |
|
"maxLength": 255, |
33 |
|
"pattern": "^[^,;()'\"]+$", |
34 |
|
} |
35 |
1 |
string_schema = {"type": "string", "minLength": 1, "maxLength": 255} |
36 |
1 |
ssh_key_schema = {"type": "string", "minLength": 1} |
37 |
1 |
id_schema = { |
38 |
|
"type": "string", |
39 |
|
"pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$", |
40 |
|
} |
41 |
1 |
bool_schema = {"type": "boolean"} |
42 |
1 |
null_schema = {"type": "null"} |
43 |
1 |
object_schema = {"type": "object"} |
44 |
|
|
45 |
1 |
deploy_item_schema = { |
46 |
|
"title": "deploy item validation. Each vld, vdu, flavor, image, ...", |
47 |
|
"$schema": "http://json-schema.org/draft-04/schema#", |
48 |
|
"type": "object", |
49 |
|
"properties": { |
50 |
|
"id": string_schema, |
51 |
|
"vim_info": object_schema, |
52 |
|
"common_id": string_schema, |
53 |
|
}, |
54 |
|
"additionalProperties": True, |
55 |
|
} |
56 |
|
|
57 |
1 |
deploy_item_list = { |
58 |
|
"type": "array", |
59 |
|
"items": deploy_item_schema, |
60 |
|
} |
61 |
|
|
62 |
1 |
deploy_vnf_schema = { |
63 |
|
"title": "deploy.vnf.item validation", |
64 |
|
"$schema": "http://json-schema.org/draft-04/schema#", |
65 |
|
"type": "object", |
66 |
|
"properties": { |
67 |
|
"_id": id_schema, |
68 |
|
"vdur": deploy_item_list, |
69 |
|
"vld": deploy_item_list, |
70 |
|
}, |
71 |
|
"additionalProperties": True, |
72 |
|
"required": ["_id"], |
73 |
|
} |
74 |
|
|
75 |
1 |
deploy_action_schema = { |
76 |
|
"title": "deploy.action validation", |
77 |
|
"$schema": "http://json-schema.org/draft-04/schema#", |
78 |
|
"type": "object", |
79 |
|
"properties": { |
80 |
|
"action": {"enum": ["inject_ssh_key"]}, |
81 |
|
"key": ssh_key_schema, |
82 |
|
"user": string_schema, |
83 |
|
"password": string_schema, |
84 |
|
}, |
85 |
|
"additionalProperties": False, |
86 |
|
"required": ["action"], |
87 |
|
} |
88 |
|
|
89 |
1 |
deploy_schema = { |
90 |
|
"title": "deploy input validation", |
91 |
|
"$schema": "http://json-schema.org/draft-04/schema#", |
92 |
|
"type": "object", |
93 |
|
"properties": { |
94 |
|
"action_id": string_schema, |
95 |
|
"cloud_init_content": object_schema, |
96 |
|
"name": string_schema, |
97 |
|
"action": deploy_action_schema, |
98 |
|
"vnf": { |
99 |
|
"type": "array", |
100 |
|
"items": deploy_vnf_schema, |
101 |
|
}, |
102 |
|
"image": deploy_item_list, |
103 |
|
"flavor": deploy_item_list, |
104 |
|
"ns": { |
105 |
|
"type": "object", |
106 |
|
"properties": { |
107 |
|
"vld": deploy_item_list, |
108 |
|
}, |
109 |
|
}, |
110 |
|
"affinity-or-anti-affinity-group": deploy_item_list, |
111 |
|
}, |
112 |
|
"additionalProperties": False, |
113 |
|
} |
114 |
|
|
115 |
1 |
rebuild_schema = { |
116 |
|
"$schema": "http://json-schema.org/draft-04/schema#", |
117 |
|
"vm_rebuild": { |
118 |
|
"type": "array", |
119 |
|
"items": { |
120 |
|
"type": "object", |
121 |
|
"properties": { |
122 |
|
"vdu-id": id_schema, |
123 |
|
"vim_name": name_schema, |
124 |
|
"member-vnf-index": name_schema, |
125 |
|
}, |
126 |
|
}, |
127 |
|
"additionalProperties": True, |
128 |
|
}, |
129 |
|
} |
130 |
|
|
131 |
|
|
132 |
1 |
class ValidationError(Exception): |
133 |
1 |
def __init__(self, message, http_code=HTTPStatus.UNPROCESSABLE_ENTITY): |
134 |
0 |
self.http_code = http_code |
135 |
0 |
Exception.__init__(self, message) |
136 |
|
|
137 |
|
|
138 |
1 |
def validate_input(indata, schema_to_use): |
139 |
|
""" |
140 |
|
Validates input data against json schema |
141 |
|
:param indata: user input data. Should be a dictionary |
142 |
|
:param schema_to_use: jsonschema to test |
143 |
|
:return: None if ok, raises ValidationError exception on error |
144 |
|
""" |
145 |
0 |
try: |
146 |
0 |
if schema_to_use: |
147 |
0 |
js_v(indata, schema_to_use) |
148 |
|
|
149 |
0 |
return None |
150 |
0 |
except js_e.ValidationError as e: |
151 |
0 |
if e.path: |
152 |
0 |
error_pos = "at '" + ":".join(map(str, e.path)) + "'" |
153 |
|
else: |
154 |
0 |
error_pos = "" |
155 |
|
|
156 |
0 |
raise ValidationError("Format error {} '{}' ".format(error_pos, e.message)) |
157 |
0 |
except js_e.SchemaError: |
158 |
0 |
raise ValidationError( |
159 |
|
"Bad json schema {}".format(schema_to_use), |
160 |
|
http_code=HTTPStatus.INTERNAL_SERVER_ERROR, |
161 |
|
) |