Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
Add Schema definition
Browse files Browse the repository at this point in the history
  • Loading branch information
F-X64 authored and major committed Nov 2, 2022
1 parent 81d7c76 commit 530a52d
Show file tree
Hide file tree
Showing 4 changed files with 301 additions and 2 deletions.
55 changes: 53 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ boto3 = "^1.24.86"
requests = "^2.28.1"
google-cloud-compute = "^1.6.0"
click = "^8.1.3"
jsonschema = "^4.16.0"

[tool.poetry.group.dev.dependencies]
pytest = "^7.1.3"
Expand Down
107 changes: 107 additions & 0 deletions src/rhelocator/update_images/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from __future__ import annotations

from jsonschema import Draft202012Validator
from jsonschema import SchemaError
from jsonschema import ValidationError


SCHEMA = {
"$schema": "https://json-schema.org/draft/2020-12/schema#",
"definitions": {
"defaults": {
"type": "object",
"properties": {
"name": {"type": "string", "description": "Human readable image name"},
"version": {
"type": "string",
"description": "RHEL image version following MAJOR.MINOR.PATCH",
},
"imageId": {
"type": "string",
"description": "Image ID used for running the image",
},
"date": {
"type": "string",
"description": "Date of image release in international date format",
},
"virt": {"type": "string", "description": "Hypervisor Type"},
},
},
"aws": {
"type": "object",
"description": "AWS RHEL Image Data",
"$ref": "#/definitions/defaults",
"properties": {
"selflink": {
"description": "URL for direct access from cloud console",
"format": "uri",
"pattern": r"^https://console\.aws\.amazon\.com/ec2/home\?region=[a-z0-9-]*#launchAmi=ami-[a-z0-9]*", # noqa: E501
},
"region": {
"type": "string",
"description": "Region of image availability",
},
},
"required": [
"name",
"version",
"imageId",
"date",
"virt",
"selflink",
"region",
],
},
"azure": {
"type": "object",
"description": "Azure RHEL Image Data",
"$ref": "#/definitions/defaults",
"required": ["name", "version", "imageId", "date", "virt"],
},
"google": {
"type": "object",
"description": "Google RHEL Image Data",
"$ref": "#/definitions/defaults",
"properties": {
"selflink": {
"description": "URL for direct access from cloud console",
"format": "uri",
"pattern": r"^https://console.cloud.google.com/compute/imagesDetail/projects/rhel-cloud/global/images/[a-z0-9-]*", # noqa: E501
}
},
"required": ["name", "version", "imageId", "date", "virt", "selflink"],
},
},
"additionalProperties": False,
"required": ["images"],
"description": "Prepared Image Date for cloud image locator",
"$ref": "#/definitions/defaults",
"properties": {
"images": {
"type": "object",
"additionalProperties": False,
"description": "Prepared Image Data",
"minProperties": 1,
"properties": {
"aws": {"type": "array", "items": {"$ref": "#/definitions/aws"}},
"azure": {"type": "array", "items": {"$ref": "#/definitions/azure"}},
"google": {"type": "array", "items": {"$ref": "#/definitions/google"}},
},
}
},
}


def validate_json(data: str) -> None:
try:
validator = Draft202012Validator(SCHEMA)
errors = sorted(validator.iter_errors(data), key=lambda e: e.path)

if errors:
error_message = "Error validating image data: "
for error in errors:
error_message += f"[{error.schema_path}]: {error.message}; "
raise ValidationError(message=error_message)

except (ValidationError, SchemaError) as e:
raise ValidationError(e.message)
140 changes: 140 additions & 0 deletions tests/update_images/test_json_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""Test image updates from remote cloud APIs."""
from __future__ import annotations

import pytest

from jsonschema import ValidationError

from rhelocator.update_images import schema


def test_valid_image_data_validation():
"""Test image data validation with valid input."""
image_data = {
"images": {
"aws": [
{
"name": "some name",
"version": "some version",
"imageId": "some id",
"date": "some date",
"virt": "some virt",
"selflink": "https://console.aws.amazon.com/ec2/home?region=eu-north-1#launchAmi=ami-0e02b69290bcd7b69", # noqa: E501
"region": "some region",
}
],
"azure": [
{
"name": "some name",
"version": "some version",
"imageId": "some id",
"date": "some date",
"virt": "some virt",
}
],
"google": [
{
"name": "some name",
"version": "some version",
"imageId": "some id",
"date": "some date",
"virt": "some virt",
"selflink": "https://console.cloud.google.com/compute/imagesDetail/projects/rhel-cloud/global/images/rhel-7-v20220719", # noqa: E501
}
],
}
}

try:
schema.validate_json(image_data)
except ValidationError as exc:
raise AssertionError(f"Validating proper image data raised an exception! {exc}")


def test_incomplete_image_data_validation():
"""Test image data validation with incomplete input."""
image_data = {
"images": {
"aws": [
{
"name": "some name",
"version": "some version",
"imageId": "some id",
"virt": "some virt",
"selflink": "https://console.aws.amazon.com/ec2/home?region=eu-north-1#launchAmi=ami-0e02b69290bcd7b69", # noqa: E501
"region": "some region",
}
]
}
}

with pytest.raises(ValidationError, match=r".*'date' is a required property.*"):
schema.validate_json(image_data)


def test_invalid_image_data_validation():
"""Test image data validation with invalid input type."""
image_data = {
"images": {
"aws": [
{
"name": "some name",
"version": False,
"imageId": "some id",
"virt": "some virt",
"date": "some date",
"selflink": "https://console.aws.amazon.com/ec2/home?region=eu-north-1#launchAmi=ami-0e02b69290bcd7b69", # noqa: E501
"region": "some region",
}
]
}
}

with pytest.raises(ValidationError, match=r".*False is not of type 'string'*"):
schema.validate_json(image_data)


def test_invalid_extra_image_data_validation():
"""Test image data validation with invalid extrea input data."""
image_data = {
"images": {
"oracle": [
{
"name": "some name",
"version": "some version",
"imageId": "some id",
"virt": "some virt",
"date": "some date",
"selflink": "https://console.aws.amazon.com/ec2/home?region=eu-north-1#launchAmi=ami-0e02b69290bcd7b69", # noqa: E501
"region": "some region",
}
]
}
}

with pytest.raises(
ValidationError, match=r".*Additional properties are not allowed*"
):
schema.validate_json(image_data)


def test_malicious_url():
"""Test image data validation with malicious url injection."""
image_data = {
"images": {
"aws": [
{
"name": "some name",
"version": "some version",
"imageId": "some id",
"virt": "some virt",
"date": "some date",
"selflink": "http://some-evil-url.com/?https://console.aws.amazon.com/ec2/home?region=eu-north-1#launchAmi=ami-0e02b69290bcd7b69", # noqa: E501
"region": "some region",
}
]
}
}

with pytest.raises(ValidationError, match=r".*does not match*"):
schema.validate_json(image_data)

0 comments on commit 530a52d

Please sign in to comment.