1 # ============LICENSE_START===============================================
2 # Copyright (C) 2023 Nordix Foundation. All rights reserved.
3 # Copyright (C) 2023 OpenInfra Foundation Europe. All rights reserved.
4 # ========================================================================
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 # ============LICENSE_END=================================================
27 from pathlib import Path
28 from flask import Flask, request, Response
29 from jsonschema import validate
30 from var_declaration import policy_instances, policy_types, policy_status, callbacks, forced_settings, policy_fingerprint, hosts_set, data_delivery_counter, app
31 from maincommon import check_apipath, apipath, get_supported_interfaces_response, extract_host_name
34 TEXT_PLAIN='text/plain'
35 APPL_JSON='application/json'
40 # app is created in var_declarations
42 import payload_logging # app var need to be initialized
45 @app.route('/', methods=['GET'])
48 return Response("OK", 200, mimetype=TEXT_PLAIN)
50 #Return the current and all supported yamls for the this container
51 @app.route('/container_interfaces', methods=['GET'])
52 def container_interfaces():
54 return get_supported_interfaces_response()
56 #Delete all created instances and status
57 @app.route('/deleteinstances', methods=['POST'])
58 def delete_instances():
60 for i in policy_instances.keys():
61 policy_instances[i]={}
64 forced_settings['code']=None
65 forced_settings['delay']=None
66 policy_fingerprint.clear()
67 return Response("All policy instances deleted", 200, mimetype=TEXT_PLAIN)
69 #Delete all - all reset
70 @app.route('/deleteall', methods=['POST'])
72 global data_delivery_counter
74 policy_instances.clear()
78 forced_settings['code']=None
79 forced_settings['delay']=None
80 policy_fingerprint.clear()
81 data_delivery_counter=0
82 return Response("All policy instances and types deleted", 200, mimetype=TEXT_PLAIN)
85 @app.route('/policytype', methods=['PUT'])
88 policy_type_id=request.args.get('id')
89 if (policy_type_id is None):
90 return Response('Parameter <id> missing in request', status=400, mimetype=TEXT_PLAIN)
94 data = json.loads(data)
96 return Response("The policy type is corrupt or missing", 400, mimetype=TEXT_PLAIN)
98 if ('policySchema' not in data.keys()):
99 return Response("The policy type atribute policySchema is missing", 400, mimetype=TEXT_PLAIN)
102 if (policy_type_id in policy_types.keys()):
104 if (len(policy_instances[policy_type_id]) > 0):
105 return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
107 policy_types[policy_type_id]=data
108 policy_instances[policy_type_id]={}
109 return Response("Policy type " + policy_type_id + " is OK.", retcode, mimetype=TEXT_PLAIN)
111 #Delete a policy type
112 @app.route('/policytype', methods=['DELETE'])
113 def del_policytype():
115 policy_type_id=request.args.get('id')
116 if (policy_type_id is None):
117 return Response('Parameter <id> missing in request', status=400, mimetype=TEXT_PLAIN)
119 if (policy_type_id in policy_types.keys()):
120 if (len(policy_instances[policy_type_id]) > 0):
121 return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
123 del policy_types[policy_type_id]
124 del policy_instances[policy_type_id]
125 return Response("Policy type " + policy_type_id + " is OK.", 204, mimetype=TEXT_PLAIN)
127 return Response("Policy type " + policy_type_id + " not found.", 204, mimetype=TEXT_PLAIN)
130 # Get all policy type ids
131 @app.route('/policytypes', methods=['GET'])
132 def get_policytype_ids():
134 return (json.dumps(list(policy_instances.keys())), 200)
137 #Set force response for one A1 response
138 #/forceresponse?code=<responsecode>
139 @app.route('/forceresponse', methods=['POST'])
143 forced_settings['code']=request.args.get('code')
145 forced_settings['code']=None
146 return Response("Force response code: " + str(forced_settings['code']) + " set for one single A1 response", 200, mimetype=TEXT_PLAIN)
148 #Set force delay response, in seconds, for all A1 responses
149 #/froceesponse?delay=<seconds>
150 @app.route('/forcedelay', methods=['POST'])
154 forced_settings['delay']=request.args.get('delay')
156 forced_settings['delay']=None
157 return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all A1 responses", 200, mimetype=TEXT_PLAIN)
160 #Set status and reason
161 #/status?policyid=<policyid>&status=<status>[&reason=<reason>]
162 @app.route('/status', methods=['PUT'])
165 policy_id=request.args.get('policyid')
166 if (policy_id is None):
167 return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
168 if policy_id not in policy_status.keys():
169 return Response('Policyid: '+policy_id+' not found.', status=404, mimetype=TEXT_PLAIN)
170 status=request.args.get('status')
172 return Response('Parameter <status> missing in request', status=400, mimetype=TEXT_PLAIN)
173 reason=request.args.get('reason')
175 ps["enforceStatus"] = status
176 msg="Status set to "+status
177 if (reason is not None):
178 ps["enforceReason"] = reason
179 msg=msg+" and "+reason
180 policy_status[policy_id] = ps
181 msg=msg+" for policy: " + policy_id
182 return Response(msg, 200, mimetype=TEXT_PLAIN)
185 #/status?policyid=<policyid>
186 @app.route('/sendstatus', methods=['POST'])
188 policyid=request.args.get('policyid')
189 if (policyid is None):
190 return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
192 if (policyid not in policy_status.keys()):
193 return Response('Policyid: '+policyid+' not found.', status=404, mimetype=TEXT_PLAIN)
195 ps=policy_status[policyid]
196 cb=callbacks[policyid]
198 resp=requests.post(cb,json=json.dumps(ps), verify=False) # NOSONAR
200 return Response('Post status failed, could not send to: '+str(cb), status=500, mimetype=TEXT_PLAIN)
201 if (resp.status_code<199 & resp.status_code > 299):
202 return Response('Post status failed with code: '+resp.status_code, status=500, mimetype=TEXT_PLAIN)
204 return Response(None, 204, mimetype=APPL_JSON)
206 #Receive status (only for testing callbacks)
208 @app.route('/statustest', methods=['POST', 'PUT'])
212 data = json.loads(data)
214 return Response("The status data is corrupt or missing.", 400, mimetype=TEXT_PLAIN)
216 return Response(json.dumps(data), 200, mimetype=APPL_JSON)
218 #Receive a data delivery package
220 @app.route('/datadelivery', methods=['POST'])
222 global data_delivery_counter
225 data = json.loads(data)
227 return Response("The data is corrupt or missing.", 400, mimetype=TEXT_PLAIN)
228 data_delivery_counter += 1
229 return Response("", 200, mimetype=TEXT_PLAIN)
233 @app.route('/counter/<string:countername>', methods=['GET'])
234 def getcounter(countername):
236 if (countername == "num_instances"):
237 return Response(str(len(policy_fingerprint)), 200, mimetype=TEXT_PLAIN)
238 elif (countername == "num_types"):
239 return Response(str(len(policy_instances)),200, mimetype=TEXT_PLAIN)
240 elif (countername == "interface"):
243 return Response(str(pp[len(pp)-1]),200, mimetype=TEXT_PLAIN)
244 elif (countername == "remote_hosts"):
245 hosts=",".join(hosts_set)
246 return str(hosts),200
247 elif (countername == "datadelivery"):
248 return Response(str(data_delivery_counter),200, mimetype=TEXT_PLAIN)
250 return Response("Counter name: "+countername+" not found.",404, mimetype=TEXT_PLAIN)
253 if len(sys.argv) >= 2:
254 if isinstance(sys.argv[1], int):
255 port_number = sys.argv[1]
257 if __name__ == '__main__':
258 # Use Uvicorn to run the combined app
259 uvicorn.run(app, host="127.0.0.1", port=port_number, log_level="info")