1 # ============LICENSE_START===============================================
2 # Copyright (C) 2021-2023 Nordix Foundation. All rights reserved.
3 # ========================================================================
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 # ============LICENSE_END=================================================
22 from datetime import datetime
23 from flask import request, Response
24 from jsonschema import validate
25 from var_declaration import policy_instances, policy_types, policy_status, policy_fingerprint, callbacks, forced_settings, hosts_set, jobs, data_delivery
26 from models.enforceStatus import EnforceStatus
27 from utils import calcFingerprint
28 from maincommon import extract_host_name, is_duplicate_check
29 from payload_logging import is_payload_logging
32 APPL_JSON = 'application/json'
34 #Helper funtion to log http reponse
35 def log_resp_text(msg):
37 if (is_payload_logging()):
38 print("-----Error description-----")
41 # API Function: Health check
42 def a1_controller_get_healthcheck():
44 extract_host_name(hosts_set, request)
46 if ((r := check_modified_response()) is not None):
51 # API Function: Get all policy type ids
52 def a1_controller_get_all_policy_types():
53 extract_host_name(hosts_set, request)
55 if ((r := check_modified_response()) is not None):
58 res = list(policy_instances.keys())
59 res = list(map(int, res))
60 return Response(json.dumps(res), 200, mimetype=APPL_JSON)
62 # API Function: Get a policy type
63 def a1_controller_get_policy_type(policy_type_id):
64 extract_host_name(hosts_set, request)
66 if ((r := check_modified_response()) is not None):
69 policy_type_id=str(policy_type_id)
71 if (policy_type_id not in policy_types.keys()):
72 log_resp_text("Policy type id not found")
75 return Response(json.dumps(policy_types[policy_type_id]), 200, mimetype=APPL_JSON)
77 # API Function: Delete a policy type
78 def a1_controller_delete_policy_type(policy_type_id):
80 extract_host_name(hosts_set, request)
82 if ((r := check_modified_response()) is not None):
85 policy_type_id=str(policy_type_id)
87 if (policy_type_id not in policy_instances.keys()):
88 log_resp_text("Policy type not found")
91 if (len(policy_instances[policy_type_id]) > 0):
92 log_resp_text("Policy type cannot be removed, instances exists")
95 del policy_instances[policy_type_id]
96 del policy_types[policy_type_id]
101 # API Function: Create a policy type
102 def a1_controller_create_policy_type(policy_type_id):
104 extract_host_name(hosts_set, request)
106 if ((r := check_modified_response()) is not None):
112 return Response("The policy type id is not an int", 400, mimetype='text/plain')
114 policy_type_id=str(policy_type_id)
116 if (policy_type_id in policy_instances.keys()):
117 if (len(policy_instances[policy_type_id]) > 0):
118 log_resp_text("Policy type id already exists")
123 data = json.loads(data)
125 log_resp_text("Policy type validation failure")
128 if (('name' not in data.keys()) or ('description' not in data.keys()) or ('policy_type_id' not in data.keys()) or ('create_schema' not in data.keys())):
129 log_resp_text("Parameters missing in policy type")
132 if (policy_type_id not in policy_instances.keys()):
133 policy_instances[policy_type_id]={}
135 policy_types[policy_type_id]=data
140 # API Function: Get all policy ids for a type
141 def a1_controller_get_all_instances_for_type(policy_type_id):
143 extract_host_name(hosts_set, request)
145 if ((r := check_modified_response()) is not None):
148 policy_type_id=str(policy_type_id)
150 if (policy_type_id not in policy_instances.keys()):
151 log_resp_text("Policy type id not found")
154 res = list(policy_instances[policy_type_id].keys())
155 return Response(json.dumps(res), 200, mimetype=APPL_JSON)
157 # API Function: Get a policy instance
158 def a1_controller_get_policy_instance(policy_type_id, policy_instance_id):
160 extract_host_name(hosts_set, request)
162 if ((r := check_modified_response()) is not None):
165 policy_type_id=str(policy_type_id)
167 if (policy_type_id not in policy_instances.keys()):
168 log_resp_text("Policy type id not found")
171 if (policy_instance_id not in policy_instances[policy_type_id].keys()):
172 log_resp_text("Policy instance id not found")
175 return Response(json.dumps(policy_instances[policy_type_id][policy_instance_id]), 200, mimetype=APPL_JSON)
177 # API function: Delete a policy
178 def a1_controller_delete_policy_instance(policy_type_id, policy_instance_id):
180 extract_host_name(hosts_set, request)
182 if ((r := check_modified_response()) is not None):
185 policy_type_id=str(policy_type_id)
187 if (policy_type_id not in policy_instances.keys()):
188 log_resp_text("Policy type id not found")
191 if (policy_instance_id not in policy_instances[policy_type_id].keys()):
192 log_resp_text("Policy instance id not found")
195 if (is_duplicate_check()):
196 fp_previous=calcFingerprint(policy_instances[policy_type_id][policy_instance_id], policy_type_id)
198 fp_previous=policy_instance_id
200 del policy_fingerprint[fp_previous]
201 del policy_instances[policy_type_id][policy_instance_id]
202 del policy_status[policy_instance_id]
203 callbacks.pop(policy_instance_id)
208 # API function: Create/update a policy
209 def a1_controller_create_or_replace_policy_instance(policy_type_id, policy_instance_id):
211 extract_host_name(hosts_set, request)
213 if ((r := check_modified_response()) is not None):
216 policy_type_id=str(policy_type_id)
218 if (policy_type_id not in policy_instances.keys()):
219 log_resp_text("Policy type id not found")
224 data = json.loads(data)
226 log_resp_text("Policy json error")
230 validate(instance=data, schema=policy_types[policy_type_id]['create_schema'])
232 log_resp_text("Policy validation error")
236 if policy_instance_id in policy_instances[policy_type_id].keys():
237 if (is_duplicate_check()):
238 fp_previous=calcFingerprint(policy_instances[policy_type_id][policy_instance_id], policy_type_id)
240 fp_previous=policy_instance_id
243 if (policy_instance_id in policy_fingerprint.values()):
244 log_resp_text("Policy id already exist for other type")
247 if is_duplicate_check():
248 fp = calcFingerprint(data, policy_type_id)
250 fp = policy_instance_id
252 if (fp in policy_fingerprint.keys()) and is_duplicate_check():
253 p_id = policy_fingerprint[fp]
254 if (p_id != policy_instance_id):
255 log_resp_text("Policy json duplicate of other instance")
258 if fp_previous is not None:
259 del policy_fingerprint[fp_previous]
261 policy_fingerprint[fp]=policy_instance_id
263 noti = request.args.get('notificationDestination')
264 callbacks[policy_instance_id] = noti
266 policy_instances[policy_type_id][policy_instance_id]=data
268 enforceStatus = EnforceStatus("NOT_ENFORCED", "OTHER_REASON")
269 policy_status[policy_instance_id] = enforceStatus.to_dict()
271 # return Response(json.dumps(data), 200, mimetype=APPL_JSON)
274 # API function: Get policy status
275 def a1_controller_get_policy_instance_status(policy_type_id, policy_instance_id):
277 extract_host_name(hosts_set, request)
279 if ((r := check_modified_response()) is not None):
282 policy_type_id=str(policy_type_id)
283 if (policy_type_id not in policy_instances.keys()):
284 log_resp_text("Policy type id not found")
287 if (policy_instance_id not in policy_instances[policy_type_id].keys()):
288 log_resp_text("Policy instance id not found")
291 return Response(json.dumps(policy_status[policy_instance_id]), 200, mimetype=APPL_JSON)
293 # API function: Receive a data delivery package
294 def a1_controller_data_delivery():
296 extract_host_name(hosts_set, request)
297 if ((r := check_modified_response()) is not None):
302 data = json.loads(data)
306 log_resp_text("no job id defined for this data delivery")
309 log_resp_text("The data is corrupt or missing.")
311 data_delivery.append(data)
312 return (None, 200) # Should A1 and the A1 Simulator return 201 for creating a new resource?
314 # Helper: Create a response object if forced http response code is set
315 def get_forced_response():
317 response_code=forced_settings['code']
318 if (response_code is not None):
319 forced_settings['code'] = None
320 return (None, response_code)
323 # Helper: Delay if delayed response code is set
326 if (forced_settings['delay'] is not None):
328 val=int(forced_settings['delay'])
333 # Helper: Check if response shall be delayed or a forced response shall be sent
334 def check_modified_response():
336 return get_forced_response()