Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GitHub ci jsonschema/v13 #797

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ jobs:
libjansson-dev \
libpython2.7 \
libnss3-dev \
libssl-dev \
make \
parallel \
python3-distutils \
Expand All @@ -71,6 +72,10 @@ jobs:
- run: cargo install --force --debug cbindgen
- run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- uses: actions/checkout@v2
- name: Build jsonschema-rs-iter
working-directory: jsonschema-rs-iter
run: |
cargo install --path .
- run: python3 ./run.py --self-test
- run: git clone https://github.com/OISF/suricata -b ${{ matrix.branch }}
- run: git clone https://github.com/OISF/libhtp suricata/libhtp
Expand All @@ -84,6 +89,7 @@ jobs:
working-directory: suricata
run: python3 ../run.py --quiet
- name: Running check-eve
if: ${{ matrix.branch == 'master' }}
run: python3 ./check-eve.py
- name: Running suricata-verify with different output dir
working-directory: suricata
Expand Down Expand Up @@ -126,6 +132,7 @@ jobs:
libevent-devel \
libmaxminddb-devel \
libpcap-devel \
openssl-devel \
libtool \
lz4-devel \
make \
Expand All @@ -144,6 +151,10 @@ jobs:
- run: cargo install --force --debug cbindgen
- run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- uses: actions/checkout@v2
- name: Build jsonschema-rs-iter
working-directory: jsonschema-rs-iter
run: |
cargo install --path .
- run: python3 ./run.py --self-test
- run: git clone https://github.com/OISF/suricata -b ${{ matrix.branch }}
- run: git clone https://github.com/OISF/libhtp suricata/libhtp
Expand All @@ -157,4 +168,5 @@ jobs:
working-directory: suricata
run: python3 ../run.py --quiet
- name: Running check-eve
if: ${{ matrix.branch == 'master' }}
run: python3 ./check-eve.py
46 changes: 27 additions & 19 deletions check-eve.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,29 @@
import os.path
import argparse
import json
import subprocess
from jsonschema import validate
from jsonschema.exceptions import ValidationError

def validate_json(args, dirpath, schema, isDirectory):
json_filename = dirpath
if isDirectory:
json_filename = os.path.join(dirpath, 'eve.json')

def validate_json(args, json_filename, schema):
status = "OK"
errors = []

with open(json_filename) as f:
for line in f:
obj = json.loads(line)
try:
validate(instance = obj, schema=schema)
except ValidationError as err:
status = "FAIL"
errors.append(err.message)

if not args.python_validator:
cp = subprocess.run(["jsonschema-rs-iter", "-s", schema, "--", json_filename])
if cp.returncode != 0:
status = "FAIL"
errors.append(cp.stdout)
else:
with open(json_filename) as f:
for line in f:
obj = json.loads(line)
try:
validate(instance = obj, schema=schema)
except ValidationError as err:
status = "FAIL"
errors.append(err.message)

if not args.quiet:
if status == "FAIL":
print("===> %s: FAIL " % json_filename)
Expand All @@ -63,27 +66,32 @@ def main():

parser = argparse.ArgumentParser(description="Validation schema")
parser.add_argument("-v", dest="verbose", action="store_true")
parser.add_argument("-p", dest="python_validator", action="store_true", help="use python validator")
parser.add_argument("file", nargs="?", default=[])
parser.add_argument("-q", dest="quiet", action="store_true")
args = parser.parse_args()
TOPDIR = os.path.abspath(os.path.dirname(sys.argv[0]))
tdir = os.path.join(TOPDIR, "tests")

json_path = "{}/schema.json".format(TOPDIR)
schema = json.load(open(json_path))

if args.python_validator:
schema = json.load(open(json_path))
else:
schema = json_path

checked = 0
passed = 0
failed = 0

isDirectory = True
argfile = args.file

if argfile:
# if the argument is a single file
if os.path.isfile(argfile):
isDirectory = False
status = validate_json(args, argfile, schema, isDirectory)
status = validate_json(args, argfile, schema)
checked += 1
if status == "OK":
passed += 1
Expand All @@ -93,12 +101,12 @@ def main():
# if the argument is a directory
elif os.path.isdir(argfile):
tdir = argfile

if isDirectory:
# os.walk for eve.json files and validate each one
for dirpath, dirnames, filenames in os.walk(tdir):
if 'eve.json' in filenames:
status = validate_json(args, dirpath, schema, isDirectory)
status = validate_json(args, os.path.join(dirpath, 'eve.json'), schema)
checked += 1
if status == "OK":
passed += 1
Expand Down
11 changes: 11 additions & 0 deletions jsonschema-rs-iter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "jsonschema-rs-iter"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
jsonschema = "0.13"
clap = { version = "3.1.6", features = ["derive"] }
serde_json = "1"
75 changes: 75 additions & 0 deletions jsonschema-rs-iter/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::{error::Error, fs, path::PathBuf, process};

use clap::Parser;
use jsonschema::JSONSchema;

type BoxErrorResult<T> = Result<T, Box<dyn Error>>;

use std::fs::File;
use std::io::BufReader;

#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Cli {
/// A path to a JSON instance (i.e. filename.json) to validate (may be specified multiple times).
#[clap(last = true)]
instances: Vec<PathBuf>,

/// The JSON Schema to validate with (i.e. schema.json).
#[clap(short, long)]
schema: PathBuf,
}

pub fn main() -> BoxErrorResult<()> {
let config = Cli::parse();

let success = validate_instances(&config.instances, config.schema)?;

if !success {
process::exit(1);
}

Ok(())
}

fn validate_instances(instances: &[PathBuf], schema: PathBuf) -> BoxErrorResult<bool> {
let mut success = true;

let schema_json = fs::read_to_string(schema)?;
let schema_json = serde_json::from_str(&schema_json)?;
match JSONSchema::compile(&schema_json) {
Ok(schema) => {
for instance in instances {
let instance_path_name = instance.to_str().unwrap();
let file = File::open(instance_path_name)?;
let reader = BufReader::new(file);
let deserializer = serde_json::Deserializer::from_reader(reader);
let iterator = deserializer.into_iter::<serde_json::Value>();
let mut success_i = true;
for item in iterator {
let instance_json = item?;
let validation = schema.validate(&instance_json);
match validation {
Ok(_) => {}
Err(errors) => {
success = false;
success_i = false;
println!("{} - INVALID. Errors:", instance_path_name);
for (i, e) in errors.enumerate() {
println!("{}.{} {}", i + 1, e.instance_path, e);
}
}
}
}
if success_i {
println!("{} - VALID", instance_path_name);
}
}
}
Err(error) => {
println!("Schema is invalid. Error: {}", error);
success = false;
}
}
Ok(success)
}
12 changes: 10 additions & 2 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@
import yaml

# Check if we can validate EVE files against the schema.
global VALIDATE_EVE
try:
import jsonschema
VALIDATE_EVE = True
check_output = subprocess.run(["jsonschema-rs-iter", "-V"], capture_output=True)
if check_output.returncode != 0:
VALIDATE_EVE = False
except:
VALIDATE_EVE = False

Expand Down Expand Up @@ -948,7 +951,9 @@ def main():
if args.self_test:
return unittest.main(argv=[sys.argv[0]])

print("Warning: EVE files will not be validated: jsonschema module not found.")
global VALIDATE_EVE
if not VALIDATE_EVE:
print("Warning: EVE files will not be valided: jsonschema-rs-iter program not found.")

TOPDIR = os.path.abspath(os.path.dirname(sys.argv[0]))

Expand All @@ -967,6 +972,9 @@ def main():

# Create a SuricataConfig object that is passed to all tests.
suricata_config = SuricataConfig(get_suricata_version())
# only validate eve since version 7
if not is_version_compatible(version="7", suri_version=suricata_config.version, expr="gte"):
VALIDATE_EVE = False
suricata_config.valgrind = args.valgrind
tdir = os.path.join(TOPDIR, "tests")
if args.testdir:
Expand Down
Loading