2022-11-29 23:53:14 +01:00
|
|
|
class implementation_check_kind_http_request(interface_check_kind):
|
|
|
|
|
|
2022-11-30 23:03:24 +01:00
|
|
|
'''
|
|
|
|
|
[implementation]
|
|
|
|
|
'''
|
|
|
|
|
def parameters_schema(self):
|
|
|
|
|
return {
|
|
|
|
|
"type": "object",
|
|
|
|
|
"additionalProperties": False,
|
|
|
|
|
"properties": {
|
|
|
|
|
"request": {
|
|
|
|
|
"type": "object",
|
|
|
|
|
"additionalProperties": False,
|
|
|
|
|
"properties": {
|
|
|
|
|
"target": {
|
|
|
|
|
"description": "URL",
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"method": {
|
|
|
|
|
"type": "string",
|
|
|
|
|
"enum": [
|
|
|
|
|
"GET",
|
|
|
|
|
"POST"
|
|
|
|
|
],
|
|
|
|
|
"default": "GET"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"required": [
|
|
|
|
|
"target"
|
|
|
|
|
]
|
|
|
|
|
},
|
2022-12-15 15:51:07 +01:00
|
|
|
"timeout": {
|
|
|
|
|
"description": "maximum allowed execution time in seconds",
|
|
|
|
|
"type": "float",
|
|
|
|
|
"default": 5.0
|
|
|
|
|
},
|
2023-04-26 17:27:47 +02:00
|
|
|
"follow_redirects": {
|
|
|
|
|
"description": "whether redirect instructions in responses shall be followend instead of being exposed as result",
|
|
|
|
|
"type": "boolean",
|
|
|
|
|
"default": False
|
|
|
|
|
},
|
2022-11-30 23:03:24 +01:00
|
|
|
"response": {
|
|
|
|
|
"type": "object",
|
|
|
|
|
"additionalProperties": False,
|
|
|
|
|
"properties": {
|
|
|
|
|
"status_code": {
|
|
|
|
|
"description": "checks whether the response status code is this",
|
|
|
|
|
"type": ["null", "integer"],
|
|
|
|
|
"default": 200
|
|
|
|
|
},
|
|
|
|
|
"headers": {
|
|
|
|
|
"description": "conjunctively checks header key-value pairs",
|
|
|
|
|
"type": "object",
|
|
|
|
|
"additionalProperties": {
|
|
|
|
|
"description": "header value",
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"properties": {
|
|
|
|
|
},
|
|
|
|
|
"required": [
|
|
|
|
|
],
|
|
|
|
|
"default": {}
|
|
|
|
|
},
|
|
|
|
|
"body_part": {
|
|
|
|
|
"description": "checks whether the response body contains this string",
|
|
|
|
|
"type": "string"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"required": [
|
|
|
|
|
]
|
|
|
|
|
},
|
2023-06-18 21:11:37 +02:00
|
|
|
"critical": {
|
2022-12-03 16:36:44 +01:00
|
|
|
"description": "whether a violation of this check shall be leveled as critical instead of concerning",
|
2022-11-30 23:03:24 +01:00
|
|
|
"type": "boolean",
|
2022-12-03 16:36:44 +01:00
|
|
|
"default": True
|
|
|
|
|
},
|
2023-06-18 21:11:37 +02:00
|
|
|
"strict": {
|
|
|
|
|
"deprecated": True,
|
|
|
|
|
"description": "alias for 'critical'",
|
|
|
|
|
"type": "boolean",
|
|
|
|
|
"default": True
|
|
|
|
|
},
|
2022-11-30 23:03:24 +01:00
|
|
|
},
|
|
|
|
|
"required": [
|
2023-06-18 21:11:37 +02:00
|
|
|
"request",
|
2022-11-30 23:03:24 +01:00
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-11-29 23:53:14 +01:00
|
|
|
'''
|
|
|
|
|
[implementation]
|
|
|
|
|
'''
|
2023-04-28 17:30:51 +02:00
|
|
|
def normalize_order_node(self, node):
|
2023-06-18 21:11:37 +02:00
|
|
|
version = (
|
|
|
|
|
"v1"
|
|
|
|
|
if (not ("critical" in node)) else
|
|
|
|
|
"v2"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if (version == "v1"):
|
|
|
|
|
node_ = dict_merge(
|
|
|
|
|
{
|
|
|
|
|
"request": {
|
|
|
|
|
"method": "GET"
|
|
|
|
|
},
|
|
|
|
|
"timeout": 5.0,
|
|
|
|
|
"follow_redirects": False,
|
|
|
|
|
"response": {
|
|
|
|
|
"status_code": 200
|
|
|
|
|
},
|
|
|
|
|
"strict": True,
|
2022-11-29 23:53:14 +01:00
|
|
|
},
|
2023-06-18 21:11:37 +02:00
|
|
|
node,
|
|
|
|
|
True
|
|
|
|
|
)
|
|
|
|
|
allowed_methods = set(["GET", "POST"])
|
|
|
|
|
if (node_["request"]["method"] not in allowed_methods):
|
|
|
|
|
raise ValueError("invalid HTTP request method: %s" % node_["request"]["method"])
|
|
|
|
|
else:
|
|
|
|
|
return {
|
|
|
|
|
"request": node_["request"],
|
|
|
|
|
"timeout": node_["timeout"],
|
|
|
|
|
"follow_redirects": node_["follow_redirects"],
|
|
|
|
|
"response": node_["response"],
|
|
|
|
|
"critical": node_["strict"],
|
|
|
|
|
}
|
|
|
|
|
elif (version == "v2"):
|
|
|
|
|
node_ = dict_merge(
|
|
|
|
|
{
|
|
|
|
|
"request": {
|
|
|
|
|
"method": "GET"
|
|
|
|
|
},
|
|
|
|
|
"timeout": 5.0,
|
|
|
|
|
"follow_redirects": False,
|
|
|
|
|
"response": {
|
|
|
|
|
"status_code": 200
|
|
|
|
|
},
|
|
|
|
|
"critical": True,
|
2022-11-29 23:53:14 +01:00
|
|
|
},
|
2023-06-18 21:11:37 +02:00
|
|
|
node,
|
|
|
|
|
True
|
|
|
|
|
)
|
|
|
|
|
allowed_methods = set(["GET", "POST"])
|
|
|
|
|
if (node_["request"]["method"] not in allowed_methods):
|
|
|
|
|
raise ValueError("invalid HTTP request method: %s" % node_["request"]["method"])
|
|
|
|
|
else:
|
|
|
|
|
return node_
|
2022-12-03 16:36:44 +01:00
|
|
|
else:
|
2023-06-18 21:11:37 +02:00
|
|
|
raise ValueError("unhandled")
|
2022-11-29 23:53:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
[implementation]
|
|
|
|
|
'''
|
2022-11-30 08:15:35 +01:00
|
|
|
def run(self, parameters):
|
|
|
|
|
if (parameters["request"]["method"] == "GET"):
|
2022-11-29 23:53:14 +01:00
|
|
|
try:
|
|
|
|
|
response = _requests.get(
|
2022-12-15 15:51:07 +01:00
|
|
|
parameters["request"]["target"],
|
2023-04-26 17:27:47 +02:00
|
|
|
timeout = parameters["timeout"],
|
|
|
|
|
allow_redirects = parameters["follow_redirects"]
|
2022-11-29 23:53:14 +01:00
|
|
|
)
|
|
|
|
|
error = None
|
|
|
|
|
except Exception as error_:
|
|
|
|
|
error = error_
|
|
|
|
|
response = None
|
2022-11-30 08:15:35 +01:00
|
|
|
elif (parameters["request"]["method"] == "POST"):
|
2022-11-29 23:53:14 +01:00
|
|
|
try:
|
|
|
|
|
response = _requests.post(
|
2022-12-15 15:51:07 +01:00
|
|
|
parameters["request"]["target"],
|
2023-04-26 17:27:47 +02:00
|
|
|
timeout = parameters["timeout"],
|
|
|
|
|
allow_redirects = parameters["follow_redirects"]
|
2022-11-29 23:53:14 +01:00
|
|
|
)
|
|
|
|
|
error = None
|
|
|
|
|
except Exception as error_:
|
|
|
|
|
error = error_
|
|
|
|
|
response = None
|
|
|
|
|
else:
|
2022-12-03 16:36:44 +01:00
|
|
|
raise ValueError("impossible")
|
|
|
|
|
if (response is None):
|
2022-11-29 23:53:14 +01:00
|
|
|
return {
|
2022-12-03 16:36:44 +01:00
|
|
|
"condition": (
|
|
|
|
|
enum_condition.critical
|
|
|
|
|
if parameters["strict"] else
|
2023-03-04 16:00:35 +01:00
|
|
|
enum_condition.concerning
|
2022-12-03 16:36:44 +01:00
|
|
|
),
|
|
|
|
|
"info": {
|
|
|
|
|
"request": parameters["request"],
|
|
|
|
|
"faults": [
|
2022-12-18 23:16:39 +01:00
|
|
|
translation_get("checks.http_request.request_failed"),
|
2022-12-03 16:36:44 +01:00
|
|
|
],
|
|
|
|
|
}
|
2022-11-29 23:53:14 +01:00
|
|
|
}
|
|
|
|
|
else:
|
2023-01-19 08:11:50 +01:00
|
|
|
faults = []
|
2022-12-03 16:36:44 +01:00
|
|
|
for (key, value, ) in parameters["response"].items():
|
|
|
|
|
if (key == "status_code"):
|
|
|
|
|
if ((value is None) or (response.status_code == value)):
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
faults.append(
|
|
|
|
|
translation_get(
|
|
|
|
|
"checks.http_request.status_code_mismatch",
|
|
|
|
|
{
|
|
|
|
|
"status_code_actual": ("%u" % response.status_code),
|
|
|
|
|
"status_code_expected": ("%u" % value),
|
|
|
|
|
}
|
2022-11-29 23:53:14 +01:00
|
|
|
)
|
2022-12-03 16:36:44 +01:00
|
|
|
)
|
|
|
|
|
elif (key == "headers"):
|
|
|
|
|
for (header_key, header_value, ) in value.items():
|
2023-04-28 13:14:27 +02:00
|
|
|
if (not (header_key in response.headers)):
|
2022-12-03 16:36:44 +01:00
|
|
|
faults.append(
|
|
|
|
|
translation_get(
|
2023-04-28 13:14:27 +02:00
|
|
|
"checks.http_request.header_missing",
|
2022-11-29 23:53:14 +01:00
|
|
|
{
|
2022-12-03 16:36:44 +01:00
|
|
|
"key": header_key,
|
|
|
|
|
"value_expected": header_value,
|
2022-11-29 23:53:14 +01:00
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
)
|
2023-04-28 13:14:27 +02:00
|
|
|
else:
|
|
|
|
|
if (not (response.headers[header_key] == header_value)):
|
|
|
|
|
faults.append(
|
|
|
|
|
translation_get(
|
|
|
|
|
"checks.http_request.header_value_mismatch",
|
|
|
|
|
{
|
|
|
|
|
"key": header_key,
|
|
|
|
|
"value_actual": response.headers[header_key],
|
|
|
|
|
"value_expected": header_value,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
pass
|
2022-12-03 16:36:44 +01:00
|
|
|
elif (key == "body_part"):
|
|
|
|
|
if (response.text.find(value) >= 0):
|
|
|
|
|
pass
|
2022-11-29 23:53:14 +01:00
|
|
|
else:
|
2022-12-03 16:36:44 +01:00
|
|
|
faults.append(
|
|
|
|
|
translation_get(
|
|
|
|
|
"checks.http_request.body_misses_part",
|
|
|
|
|
{
|
|
|
|
|
"part": value,
|
|
|
|
|
}
|
|
|
|
|
)
|
2022-11-29 23:53:14 +01:00
|
|
|
)
|
2022-12-03 16:36:44 +01:00
|
|
|
else:
|
|
|
|
|
raise ValueError("unhandled")
|
|
|
|
|
return {
|
|
|
|
|
"condition": (
|
|
|
|
|
enum_condition.ok
|
|
|
|
|
if (len(faults) <= 0) else
|
|
|
|
|
(
|
|
|
|
|
enum_condition.critical
|
|
|
|
|
if parameters["strict"] else
|
2023-03-04 16:00:35 +01:00
|
|
|
enum_condition.concerning
|
2022-12-03 16:36:44 +01:00
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
"info": {
|
|
|
|
|
"request": parameters["request"],
|
|
|
|
|
"response": {
|
|
|
|
|
"status_code": response.status_code,
|
2023-04-28 17:30:51 +02:00
|
|
|
"headers": dict(map(lambda pair: pair, response.headers.items())),
|
2022-12-03 16:36:44 +01:00
|
|
|
# "body": response.text,
|
|
|
|
|
},
|
|
|
|
|
"faults": faults,
|
2022-11-29 23:53:14 +01:00
|
|
|
}
|
2022-12-03 16:36:44 +01:00
|
|
|
}
|
2022-11-30 23:03:24 +01:00
|
|
|
|