I have a dictionary r_dict
and I want to check the every keys in the r_dict['paths']
that the key security
inside every endpoint (for example /pet/{petId}/uploadImage
) exists and inside the security, the values contains words read
or write
and append the result in the dictionary
result = {}
as result[end_point_name] = 'secure'
if key security
is present and words read
or write
is present
ELSE
result[end_point_name] ='unsecure'
The following is a dictionary r_dict
r_dict = {"paths": {
"/pet/{petId}/uploadImage": {
"post": {
"tags": [
"pet"
],
"summary": "uploads an image",
"description": "",
"operationId": "uploadFile",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "petId",
"in": "path",
"description": "ID of pet to update",
"required": true,
"type": "integer",
"format": "int64"
},
{
"name": "additionalMetadata",
"in": "formData",
"description": "Additional data to pass to server",
"required": false,
"type": "string"
},
{
"name": "file",
"in": "formData",
"description": "file to upload",
"required": false,
"type": "file"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/ApiResponse"
}
}
},
"security": [
{
"petstore_auth": [
"write:pets",
"read:pets"
]
}
]
}
},
"/pet": {
"post": {
"tags": [
"pet"
],
"summary": "Add a new pet to the store",
"description": "",
"operationId": "addPet",
"consumes": [
"application/json",
"application/xml"
],
"produces": [
"application/json",
"application/xml"
],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Pet object that needs to be added to the store",
"required": true,
"schema": {
"$ref": "#/definitions/Pet"
}
}
],
"responses": {
"405": {
"description": "Invalid input"
}
},
"security": [
{
"petstore_auth": [
"write:pets",
"read:pets"
]
}
]
},
"put": {
"tags": [
"pet"
],
"summary": "Update an existing pet",
"description": "",
"operationId": "updatePet",
"consumes": [
"application/json",
"application/xml"
],
"produces": [
"application/json",
"application/xml"
],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Pet object that needs to be added to the store",
"required": true,
"schema": {
"$ref": "#/definitions/Pet"
}
}
],
"responses": {
"400": {
"description": "Invalid ID supplied"
},
"404": {
"description": "Pet not found"
},
"405": {
"description": "Validation exception"
}
},
"security": [
{
"petstore_auth": [
"write:pets",
"read:pets"
]
}
]
}
},
"/pet/findByStatus": {
"get": {
"tags": [
"pet"
],
"summary": "Finds Pets by status",
"description": "Multiple status values can be provided with comma separated strings",
"operationId": "findPetsByStatus",
"produces": [
"application/json",
"application/xml"
],
"parameters": [
{
"name": "status",
"in": "query",
"description": "Status values that need to be considered for filter",
"required": true,
"type": "array",
"items": {
"type": "string",
"enum": [
"available",
"pending",
"sold"
],
"default": "available"
},
"collectionFormat": "multi"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
},
"400": {
"description": "Invalid status value"
}
},
"security": [
{
"petstore_auth": [
"write:pets",
"read:pets"
]
}
]
}
} }
CodePudding user response:
path "/pet" in r_dict has more than one http method unlike other paths, so have built the script to accomodate more than 1 http method in a path
result = {}
paths = r_dict['paths']
for path in paths:
path_val = paths[path]
methods = path_val.keys()
for val in methods:
key = f'{path}[{val}]'
method_data = path_val[val]
sec = method_data.get('security', None)
if sec and len(sec) > 0:
sec_tag = sec[0]
petstore_data = sec_tag['petstore_auth']
if any(item for item in petstore_data if 'read' in item or 'write' in item):
result[key] = 'secure'
else:
result[key] = 'unsecure'
else:
result[key] = 'unsecure'
print(result)
this prints the below results for r_dict, as you can see the method names are also mentioned with paths:
{
'/pet/{petId}/uploadImage[post]': 'secure',
'/pet[post]': 'secure',
'/pet[put]': 'secure',
'/pet/findByStatus[get]': 'secure'
}
CodePudding user response:
More type of methods are possible for a path (GET
, POST
, PUT
etc...) so these methods should be handled differently (I guess). I have written a solution which handles that different methods and the missing security
attributes.
You can change this line end_point_with_method = "{} -> {}".format(method.upper(), end_point)
if you want to change the keys in the result dict. BUT if you use only the path as key then the different methods won't be separated.
Code:
result = {}
for end_point, methods in r_dict["paths"].items():
for method, data in methods.items():
end_point_with_method = "{} -> {}".format(method.upper(), end_point)
if "security" in data:
for auths in [item["petstore_auth"] for item in data["security"]]:
for auth in auths:
if "write" in auth or "read" in auth:
result[end_point_with_method] = "secure"
if end_point_with_method not in result:
result[end_point_with_method] = "unsecure"
else:
result[end_point_with_method] = "unsecure"
for path, secure in result.items():
print("{} -> {}".format(path, secure))
Output:
>>> python3 test.py
POST -> /pet/{petId}/uploadImage -> secure
POST -> /pet -> secure
PUT -> /pet -> secure
GET -> /pet/findByStatus -> secure
If I change the data in PUT
method of /pet
path to:
"security": [{"petstore_auth": ["X:pets", "Y:pets"]}]
The output is:
>>> python3 test.py
POST -> /pet/{petId}/uploadImage -> secure
POST -> /pet -> secure
PUT -> /pet -> unsecure
GET -> /pet/findByStatus -> secure
If I remove the security
member competelly from PUT
method of /pet
path then output is:
>>> python3 test.py
POST -> /pet/{petId}/uploadImage -> secure
POST -> /pet -> secure
PUT -> /pet -> unsecure
GET -> /pet/findByStatus -> secure