Patch set 2: Commit message clean-up.
Issue-ID: NONRTRIC-756
Change-Id: I73bf9dd8788aeae2ca63ac0143a49bde943788e5
Signed-off-by: halil.cakal <halil.cakal@est.tech>
# ============LICENSE_END=================================================
#
+import os
import copy
import datetime
import json
import logging
import collections
import time
+import requests
from connexion import NoContent
from flask import Flask, escape, request, Response, make_response
APPL_JSON='application/json'
APPL_PROB_JSON='application/problem+json'
+EXT_SRV_URL=os.getenv('EXT_SRV_URL')
+
+
# API Function: Get all policy type ids
def get_all_policy_types():
pjson=create_problem_json(None, "Duplicate, the policy json already exists.", 400, None, policy_id)
return Response(json.dumps(pjson), 400, mimetype=APPL_PROB_JSON)
+ #Callout hooks for external server
+ #When it fails, break and return 419 HTTP status code
+ if (EXT_SRV_URL is not None):
+ resp = callout_external_server(policy_id, data, 'PUT')
+ if (resp != retcode):
+ pjson=create_error_response(resp)
+ return Response(json.dumps(pjson), 500, mimetype=APPL_PROB_JSON)
+
if (fp_previous is not None):
del policy_fingerprint[fp_previous]
return Response(json.dumps(policy_instances[policy_type_id][policy_id]), 200, mimetype=APPL_JSON)
-
# API Function: Delete a policy
def delete_policy(policyTypeId, policyId):
pjson=create_problem_json(None, "The requested policy does not exist.", 404, None, policy_id)
return Response(json.dumps(pjson), 404, mimetype=APPL_PROB_JSON)
+ #Callout hooks for external server
+ #When it fails, break and return 419 HTTP status code
+ if (EXT_SRV_URL is not None):
+ resp = callout_external_server(policy_id, None, 'DELETE')
+ if (resp != 204):
+ pjson=create_error_response(resp)
+ return Response(json.dumps(pjson), 500, mimetype=APPL_PROB_JSON)
+
if (is_duplicate_check()):
fp_previous=calcFingerprint(policy_instances[policy_type_id][policy_id], policy_type_id)
else:
callbacks.pop(policy_id)
return Response('', 204, mimetype=APPL_JSON)
-
# API Function: Get status for a policy
def get_policy_status(policyTypeId, policyId):
return Response(json.dumps(policy_status[policy_id]), status=200, mimetype=APPL_JSON)
+# Helper: Callout external server to notify it for policy operations
+# Returns 200, 201 and 204 for the success callout hooks, for the others returns 419
+def callout_external_server(policy_id, payload, operation):
+
+ target_url=EXT_SRV_URL + policy_id
+ try:
+ if (operation == 'PUT'):
+ #Suppress error when self-signed certificate is being used with verify flag
+ resp=requests.put(target_url, json=payload, timeout=10, verify=False)
+ return resp.status_code
+ elif (operation == 'DELETE'):
+ resp=requests.delete(target_url, timeout=10, verify=False)
+ return resp.status_code
+ except Exception:
+ #Return a generic unassigned HTTP status code as per iana, for all exceptions (419:Callout failed)
+ #https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
+ return 419
+
# Helper: Create a response object if forced http response code is set
def get_forced_response():
+
if (forced_settings['code'] is not None):
- pjson=create_error_response(forced_settings['code'])
+ value=forced_settings['code']
+ pjson=create_error_response(int(value))
forced_settings['code']=None
return Response(json.dumps(pjson), pjson['status'], mimetype=APPL_PROB_JSON)
return None
# Helper: Delay if delayed response code is set
def do_delay():
+
if (forced_settings['delay'] is not None):
try:
val=int(forced_settings['delay'])
# Helper: Check if response shall be delayed or a forced response shall be sent
def check_modified_response():
+
do_delay()
return get_forced_response()
# Helper: Create a problem json based on a generic http response code
def create_error_response(code):
- if code == '400':
+ if (code == 400):
return(create_problem_json(None, "Bad request", 400, "Object in payload not properly formulated or not related to the method", None))
- elif code == '404':
+ elif (code == 404):
return(create_problem_json(None, "Not found", 404, "No resource found at the URI", None))
- elif code == '405':
+ elif (code == 405):
return(create_problem_json(None, "Method not allowed", 405, "Method not allowed for the URI", None))
- elif code == '409':
+ elif (code == 409):
return(create_problem_json(None, "Conflict", 409, "Request could not be processed in the current state of the resource", None))
- elif code == '429':
+ elif (code == 419):
+ return(create_problem_json(None, "Callout failed", 419, "Callout hooks could not be processed on the external server", None))
+ elif (code == 429):
return(create_problem_json(None, "Too many requests", 429, "Too many requests have been sent in a given amount of time", None))
- elif code == '507':
+ elif (code == 507):
return(create_problem_json(None, "Insufficient storage", 507, "The method could not be performed on the resource because the provider is unable to store the representation needed to successfully complete the request", None))
- elif code == '503':
+ elif (code == 503):
return(create_problem_json(None, "Service unavailable", 503, "The provider is currently unable to handle the request due to a temporary overload", None))
else:
return(create_problem_json(None, "Unknown", code, "Not implemented response code", None))
perl_set $allow_http 'sub { return $ENV{"ALLOW_HTTP"}; }';
server { # simple reverse-proxy
- listen 8085;
- listen [::]:8085;
+ listen 9095;
+ listen [::]:9095;
server_name localhost;
if ($allow_http != true) {
return 444;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_pass http://localhost:2222;
+ proxy_pass http://localhost:3333;
}
}
server { # simple reverse-proxy
- listen 8185 ssl;
- listen [::]:8185 ssl;
+ listen 9195 ssl;
+ listen [::]:9195 ssl;
server_name localhost;
ssl_certificate /usr/src/app/cert/cert.crt;
ssl_certificate_key /usr/src/app/cert/key.crt;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_pass http://localhost:2222;
+ proxy_pass http://localhost:3333;
}
}
##
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
-}
\ No newline at end of file
+}
else:
return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all external server responses until it is resetted ", 200, mimetype=TEXT_PLAIN)
-port_number = 2222
+port_number = 3333
if len(sys.argv) >= 2:
if isinstance(sys.argv[1], int):
port_number = sys.argv[1]
if [ $1 == "nonsecure" ]; then
#Default http port for the simulator
- PORT=8085
+ PORT=9095
# Set http protocol
HTTPX="http"
else
#Default https port for the simulator
- PORT=8185
+ PORT=9195
# Set https protocol
HTTPX="https"
fi
. ../common/test_common.sh
. ../common/elapse_time_curl.sh
-echo "=== Simulator hello world ==="
+echo "=== External server hello world ==="
RESULT="OK"
do_curl GET / 200
-echo "=== Reset simulator a1policy instances ==="
+echo "=== Reset external server a1policy instances ==="
RESULT="All a1 policy instances deleted"
do_curl POST /serveradmin/deleteinstances 200
echo "PWD path: "$PWD
#Run the container in interactive mode, unsecure port 8085, secure port 8185
-docker run --rm -it -p 8085:8085 -p 8185:8185 -e ALLOW_HTTP=true --volume "$PWD/certificate:/usr/src/app/cert" --name externalserversimulator external_server
+docker run --rm -it -p 9095:9095 -p 9195:9195 -e ALLOW_HTTP=true --volume "$PWD/certificate:/usr/src/app/cert" --name externalserversimulator external_server
# Run the build_and_start with the same arg, except arg 'nonsecure|secure', as this script
print_usage() {
- echo "Usage: ./basic_test.sh nonsecure|secure duplicate-check|ignore-duplicate "
+ echo "Usage: ./basic_test.sh nonsecure|secure duplicate-check|ignore-duplicate ext-srv|ext-srv-secure|ignore-ext-srv"
exit 1
}
-if [ $# -ne 2 ]; then
+if [ $# -ne 3 ]; then
print_usage
fi
-if [ "$1" != "nonsecure" ] && [ "$1" != "secure" ]; then
+
+if [ $1 != "nonsecure" ] && [ $1 != "secure" ]; then
print_usage
fi
-if [ "$2" == "duplicate-check" ]; then
- DUP_CHECK=1
-elif [ "$2" == "ignore-duplicate" ]; then
- DUP_CHECK=0
-else
+
+if [ $2 != "duplicate-check" ] && [ $2 != "ignore-duplicate" ]; then
print_usage
fi
+if [ $3 != "ext-srv" ] && [ $3 != "ext-srv-secure" ] && [ $3 != "ignore-ext-srv" ]; then
+ print_usage
+fi
+
+
if [ $1 == "nonsecure" ]; then
#Default http port for the simulator
PORT=8085
HTTPX="https"
fi
+if [ $2 == "duplicate-check" ]; then
+ DUP_CHECK=1
+else
+ DUP_CHECK=0
+fi
+
+if [ $3 == "ext-srv" ]; then
+ #Default http port for the external server
+ PORT_EXT_SRV=9095
+ # Set http protocol for external server
+ HTTPX_EXT_SRV="http"
+ EXT_SRV_EXIST=1
+elif [ $3 == "ext-srv-secure" ]; then
+ #Default https port for the external server
+ PORT_EXT_SRV=9195
+ # Set https protocol for external server
+ HTTPX_EXT_SRV="https"
+ EXT_SRV_EXIST=1
+else
+ EXT_SRV_EXIST=0
+fi
+
. ../common/test_common.sh
RESULT="All policy instances and types deleted"
do_curl POST /deleteall 200
+#Test all admin functions in the external server
+if [ $EXT_SRV_EXIST == 1 ]; then
+ echo "=== External server, hello world ==="
+ RESULT="OK"
+ do_curl_ext_srv GET / 200
+
+ echo "=== External server, reset all ==="
+ RESULT="All a1 policy instances deleted"
+ do_curl_ext_srv POST /serveradmin/deleteinstances 200
+
+ echo "=== External server, reset force delay ==="
+ RESULT="Force delay has been resetted for all external server responses"
+ do_curl_ext_srv POST /serveradmin/forcedelay 200
+fi
+
echo "=== Get counter: interface ==="
RESULT="STD_2.0.0"
do_curl GET /counter/interface 200
RESULT="json:$res"
do_curl PUT /A1-P/v2/policytypes/STD_1/policies/pi1 201 jsonfiles/pi1.json
+if [ $EXT_SRV_EXIST == 1 ]; then
+ echo "=== External server, get a pi1 policy: pi1 ==="
+ res=$(cat jsonfiles/pi1.json)
+ RESULT="json:$res"
+ do_curl_ext_srv GET /a1policy/pi1 200
+fi
+
echo "=== API: Get policy instance pi1 of type: STD_1 ==="
res=$(cat jsonfiles/pi1.json)
RESULT="json:$res"
RESULT="json:$res"
do_curl PUT /A1-P/v2/policytypes/STD_1/policies/pi1 200 jsonfiles/pi1.json
+if [ $EXT_SRV_EXIST == 1 ]; then
+ echo "=== External server, get a pi1 policy: pi1 ==="
+ res=$(cat jsonfiles/pi1.json)
+ RESULT="json:$res"
+ do_curl_ext_srv GET /a1policy/pi1 200
+fi
+
echo "=== API: Update policy instance pi1 of type: STD_1==="
res=$(cat jsonfiles/pi1_updated.json)
RESULT="json:$res"
do_curl PUT /A1-P/v2/policytypes/STD_1/policies/pi1 200 jsonfiles/pi1_updated.json
+if [ $EXT_SRV_EXIST == 1 ]; then
+ echo "=== External server, get a pi1 policy: pi1 ==="
+ res=$(cat jsonfiles/pi1_updated.json)
+ RESULT="json:$res"
+ do_curl_ext_srv GET /a1policy/pi1 200
+fi
+
echo "=== API: Duplicate policy instance json, pi2 of type: STD_1==="
res=$(cat jsonfiles/pi1_updated.json)
if [ $DUP_CHECK == 1 ]; then
RESULT="json:$res"
do_curl PUT /A1-P/v2/policytypes/STD_1/policies/pi2 201 jsonfiles/pi1_updated.json
+ if [ $EXT_SRV_EXIST == 1 ]; then
+ echo "=== External server, get a pi2 policy: pi2 ==="
+ res=$(cat jsonfiles/pi1_updated.json)
+ RESULT="json:$res"
+ do_curl_ext_srv GET /a1policy/pi2 200
+ fi
+
echo "=== API: DELETE policy instance pi2 ==="
RESULT=""
do_curl DELETE /A1-P/v2/policytypes/STD_1/policies/pi2 204
+
+ if [ $EXT_SRV_EXIST == 1 ]; then
+ echo "=== External server, get a pi2 policy: policy instance not found ==="
+ RESULT="json:{\"title\": \"The A1 policy requested does not exist.\", \"status\": 404, \"instance\": \"pi2\"}"
+ do_curl_ext_srv GET /a1policy/pi2 404
+ fi
fi
echo "=== API: Get policy instances, shall contain pi1=="
RESULT="json:[ \"pi1\" ]"
do_curl GET /A1-P/v2/policytypes/STD_1/policies 200
+if [ $EXT_SRV_EXIST == 1 ]; then
+ echo "=== External server, get policy instances, shall contain pi1=="
+ RESULT="json:[ \"pi1\" ]"
+ do_curl_ext_srv GET /a1policies 200
+fi
+
echo "=== Put a policy type: STD_2 ==="
RESULT="Policy type STD_2 is OK."
do_curl PUT '/policytype?id=STD_2' 201 jsonfiles/std_2.json
-
echo "=== API: Duplicate policy instance id pi1 of type: STD_2==="
res=$(cat jsonfiles/pi1_updated.json)
RESULT="json:{\"title\": \"The policy id already exist for other policy type.\", \"status\": 400, \"instance\": \"pi1\"}"
RESULT="1"
do_curl GET /counter/num_instances 200
-
echo "=== Set force response code 409. ==="
RESULT="*"
do_curl POST '/forceresponse?code=409' 200
RESULT=""
do_curl DELETE /A1-P/v2/policytypes/STD_1/policies/pi1 204
-echo "=== API: Get policy instances, shall contain pi1 and pi2=="
+echo "=== API: Get policy instances, shall contain pi2=="
RESULT="json:[ \"pi2\" ]"
do_curl GET /A1-P/v2/policytypes/STD_1/policies 200
+if [ $EXT_SRV_EXIST == 1 ]; then
+ echo "=== External server, get policy instances, shall contain pi2=="
+ RESULT="json:[ \"pi2\" ]"
+ do_curl_ext_srv GET /a1policies 200
+fi
+
echo "=== API: Get policy status ==="
RESULT="json:{\"enforceStatus\": \"\", \"enforceReason\": \"\"}"
do_curl GET /A1-P/v2/policytypes/STD_1/policies/pi2/status 200
#!/bin/bash
# ============LICENSE_START===============================================
-# Copyright (C) 2021 Nordix Foundation. All rights reserved.
+# Copyright (C) 2021-2022 Nordix Foundation. All rights reserved.
# ========================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# Make sure to run the simulator with the same arg as this script
print_usage() {
- echo "Usage: ./build_and_start.sh duplicate-check|ignore-duplicate "
+ echo "Usage: ./build_and_start.sh duplicate-check|ignore-duplicate ext-srv|ext-srv-secure|ignore-ext-srv"
exit 1
}
-if [ $# -ne 1 ]; then
+if [ $# -ne 2 ]; then
print_usage
fi
+
if [ $1 == "duplicate-check" ]; then
DUP_CHECK=1
elif [ $1 == "ignore-duplicate" ]; then
print_usage
fi
-echo "Building image"
-cd ../../
+if [ $2 == "ext-srv" ]; then
+ URL="http://localhost:9095/a1policy/"
+elif [ $2 == "ext-srv-secure" ]; then
+ URL="https://localhost:9195/a1policy/"
+elif [ $2 == "ignore-ext-srv" ]; then
+ URL=""
+else
+ print_usage
+fi
-#Build the image
-docker build -t a1test .
+URL_FLAG=""
+if [ ! -z "$URL" ]; then
+ URL_FLAG="-e EXT_SRV_URL=$URL"
+fi
+
+# Stop and remove container images if they run
+echo "Stopping A1 simulator image..."
docker stop a1StdSimulator > /dev/null 2>&1
docker rm -f a1StdSimulator > /dev/null 2>&1
-echo "Starting ric-sim"
-#Run the container in interactive mode, unsecure port 8085, secure port 8185
-docker run --rm -it -p 8085:8085 -p 8185:8185 -e A1_VERSION=STD_2.0.0 -e ALLOW_HTTP=true -e REMOTE_HOSTS_LOGGING=1 -e DUPLICATE_CHECK=$DUP_CHECK --volume "$PWD/certificate:/usr/src/app/cert" --name a1StdSimulator a1test
+echo "Stopping external server image..."
+docker stop externalserversimulator > /dev/null 2>&1
+docker rm -f externalserversimulator > /dev/null 2>&1
+
+# Initialize path variables for certificate and build operations
+
+dirstd2=$PWD
+
+cd ../../
+dirnrtsim=$PWD
+
+cd test/EXT_SRV/
+dirextsrv=$PWD
+
+# Build containers
+
+cd $dirnrtsim
+echo "Building A1 simulator image..."
+docker build -t a1test .
+
+if [ ! -z "$URL" ]; then
+ cd $dirextsrv
+ echo "Building external server image..."
+ docker build -t external_server .
+fi
+
+# Run containers
+
+# Runs external_server in detached mode
+# In order to tail logs use:: docker logs -f externalserversimulator
+if [ ! -z "$URL" ]; then
+ docker run -d --network host --rm -it -p 9095:9095 -p 9195:9195 -e ALLOW_HTTP=true --volume "$dirextsrv/certificate:/usr/src/app/cert" --name externalserversimulator external_server
+fi
+
+# Runs A1 simulator
+docker run --network host --rm -it -p 8085:8085 -p 8185:8185 -e A1_VERSION=STD_2.0.0 -e ALLOW_HTTP=true -e REMOTE_HOSTS_LOGGING=1 -e DUPLICATE_CHECK=$DUP_CHECK $URL_FLAG --volume "$dirnrtsim/certificate:/usr/src/app/cert" --name a1StdSimulator a1test
fi
fi
fi
-}
\ No newline at end of file
+}
+
+do_curl_ext_srv() {
+ if [ $# -lt 3 ]; then
+ echo "Need 3 or more parameters, <http-operation> <url> <response-code> [file]: "$@
+ echo "Exiting test script....."
+ exit 1
+ fi
+ curlstr="curl -X "$1" -skw %{http_code} $HTTPX_EXT_SRV://localhost:"${PORT_EXT_SRV}${2}" -H accept:*/*"
+ if [ $# -gt 3 ]; then
+ curlstr=$curlstr" -H Content-Type:application/json --data-binary @"$4
+ fi
+ echo " CMD (${BASH_LINENO[0]}):"$curlstr
+ res=$($curlstr)
+ status=${res:${#res}-3}
+ body=${res:0:${#res}-3}
+ if [ $status -ne $3 ]; then
+ echo " Error status :"$status" Expected status: "$3
+ echo " Body :"$body
+ echo "Exiting test script....."
+ exit 1
+ else
+ echo " OK, code :"$status" (Expected)"
+ echo " Body :"$body
+ if [ "$RESULT" == "*" ]; then
+ echo " Body contents not checked"
+ elif [[ "$RESULT" == "json:"* ]]; then
+ result=${RESULT:5:${#RESULT}} #Remove 'json:' from the result string
+ res=$(python ../common/compare_json.py "$result" "$body")
+ if [ $res -eq 0 ]; then
+ echo " Expected json body :"$result
+ echo " Body as expected"
+ else
+ echo " Expected json body :"$result
+ echo "Exiting....."
+ exit 1
+ fi
+ else
+ body="$(echo $body | tr -d '\n' )"
+ if [ "$RESULT" == "$body" ]; then
+ echo " Expected body :"$RESULT
+ echo " Body as expected"
+ else
+ echo " Expected body :"$RESULT
+ echo "Exiting....."
+ exit 1
+ fi
+ fi
+ fi
+}