libjansson-dev \
libpython2.7 \
libnss3-dev \
+ libssl-dev \
make \
parallel \
python3-distutils \
- run: cargo install --force --debug cbindgen
- run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- uses: actions/checkout@v2
+ - name: Build eve-validator
+ working-directory: eve-validator
+ 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
libevent-devel \
libmaxminddb-devel \
libpcap-devel \
+ openssl-devel \
libtool \
lz4-devel \
make \
- run: cargo install --force --debug cbindgen
- run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- uses: actions/checkout@v2
+ - name: Build eve-validator
+ working-directory: eve-validator
+ 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
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(["eve-validator", "-q", "-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)
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()
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
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
# 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
--- /dev/null
+[package]
+name = "eve-validator"
+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"
--- /dev/null
+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,
+
+ /// Quiet output
+ #[clap(short, long)]
+ quiet: bool,
+}
+
+pub fn main() -> BoxErrorResult<()> {
+ let config = Cli::parse();
+
+ let success = validate_instances(&config.instances, config.schema, config.quiet)?;
+
+ if !success {
+ process::exit(1);
+ }
+
+ Ok(())
+}
+
+fn validate_instances(instances: &[PathBuf], schema: PathBuf, quiet: bool) -> 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 && !quiet {
+ println!("{} - VALID", instance_path_name);
+ }
+ }
+ }
+ Err(error) => {
+ println!("Schema is invalid. Error: {}", error);
+ success = false;
+ }
+ }
+ Ok(success)
+}
# Check if we can validate EVE files against the schema.
try:
- import jsonschema
VALIDATE_EVE = True
+ check_output = subprocess.run(["eve-validator", "-V"], capture_output=True)
+ if check_output.returncode != 0:
+ VALIDATE_EVE = False
except:
VALIDATE_EVE = False
return unittest.main(argv=[sys.argv[0]])
if not VALIDATE_EVE:
- print("Warning: EVE files will not be valided: jsonschema module not found.")
+ print("Warning: EVE files will not be valided: eve-validator program not found.")
TOPDIR = os.path.abspath(os.path.dirname(sys.argv[0]))