Skip to content

JSON document format for expressing abstract schemas, including message serialization and validation libraries.

Notifications You must be signed in to change notification settings

OpenC2-org/jadn

Repository files navigation

JADN

JSON Abstract Data Notation (JADN) is a JSON document format for defining abstract schemas. Unlike concrete schema languages such as XSD and JSON Schema, JADN defines the structure of datatypes independently of the serialization used to communicate and store data objects. An encoder/decoder (codec) validates the structure of data objects against the JADN schema and serializes/deserializes objects using a specified message format. The codec currently supports four JSON-based serialization formats, and can be extended to support XML and binary (CBOR, Protocol Buffers, etc) serializations.

JAS

JADN Abstract Syntax (or perhaps JADN Source -- JAS) is a source format used to create JADN files. Although a JADN schema is a human-readable JSON document and can be edited directly, JAS is simpler to read and write, eliminating the boilerplate (quotes, braces, brackets) inherent to JSON. A converter utility translates a schema bidirectionally between JAS and JADN formats.

JADN Python package

The JADN package contains two subpackages:

  • Codec -- Validate messages against JADN schema, serialize and deserialize messages
    • codec.py - Message encoder and decoder.
    • codec_utils.py - Utility routines used with the Codec class.
    • jadn.py - Load, validate, and save JADN schemas.
  • Convert -- Translate between JADN, JAS, and property table files.
    • jas.ebnf - EBNF grammar for JAS files
    • jas_parse.py - JAS parser generated from EBNF by the Grako grammar compiler
    • tr_jas.py - load and save JAS files
    • tr_tables.py - generate property tables (.xlsx workbook format) from JADN schema

Scripts

The JADN package was created using the Test Driven Development process, where tests containing desired results are developed first, then software is written to make the tests pass. Test scripts serve to document both example data (good and bad cases) and calling conventions for the software.

  • test_codec.py - Unit tests for encoder and decoder functions
  • test_openc2.py - Unit tests for OpenC2 commands
    • This file contains example OpenC2 commands in API format and four JSON-based formats: Verbose, Minified, Concise, and an unused format included for completeness of the codec test suite. The API format is the Python literal representation of a data item, similar but not identical to the JSON-Verbose serialization of that item ('single' vs. "double" quoted strings, True vs. true, None vs. null, etc.)
  • jadn-convert.py - Convert JADN specifications between formats (Current: JAS, JADN, and property tables. Potential: JSON schema, XSD, CDDL)

Schemas

The converter utility reads .jas and .jadn schemas from an input directory (schema) and writes converted files to an output directory (schema_gen). Output files ending in _genj are produced from JADN sources, while those ending in _gens are produced from JAS sources. After editing a JAS schema, the corresponding JADN schema (`xxx_gens.jadn') should be moved from the output to the input directory after deleting the source line at the top of the file.

  • openc2.jadn - Schema that defines the OpenC2 message format, including the target data model. The ability to import data models from multiple schema files is planned but not supported in the current version.

Getting Started

  1. Use a Python 3 environment. Install the jsonschema (for the codec) and XlsxWriter (for the converter property table generator) packages if not already installed. This software was developed under Python 3.3-3.5 and is not yet ported to Python 2.x.

  2. Look at the examples folder for example OpenC2 commands in JSON format. These files are generated automatically by the test_openc2.py unit test.

  3. An OpenC2 producer application would create a python dict containing an OpenC2 command, load the openc2.jadn schema, and encode the command:

import json
from libs.codec.codec import Codec
from libs.codec.jadn import jadn_load

command = {
    "action": "mitigate",
    "target": {
        "domain_name": {
            "value": "cdn.badco.org"}}}

schema = jadn_load("openc2.jadn")                           # Load and validate the OpenC2 schema
codec = Codec(schema, verbose_rec=True, verbose_str=True)   # Create an OpenC2 encoder/decoder (JSON-Verbose encoding)
message1 = codec.encode("OpenC2Command", command)           # Validate and encode the command
print("Sent Message =", json.dumps(message1))
  1. An OpenC2 consumer application would receive an encoded message, then decode/validate it:
received_msg = '[32,{"7":["cdn.badco.org"]}]'               # Received OpenC2 command in JSON-minified format
message2 = json.loads(received_msg)
codec.set_mode(verbose_rec=False, verbose_str=False)        # Tell codec to use JSON-minified encoding
command2 = codec.decode("OpenC2Command", message2)          # Validate and decode the command
print("Received Command =", command2)

About

JSON document format for expressing abstract schemas, including message serialization and validation libraries.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages