Skip to content

Commit

Permalink
Schema adherence validator (#77)
Browse files Browse the repository at this point in the history
* Began building YAML validation

- Introduced a new pre-commit hook script `validate-yaml.sh` to validate all committed YAML files against a predefined schema using mage's `validateallyamlfiles` command.
- Updated `.pre-commit-config.yaml` to include the new `validate-yaml-files` hook.
- Added a new schema file `ttpforge-spec.yaml` under the `docs/` directory to define the structure and properties for the TTP YAML files.
- Enhanced the `magefile.go` to include the new function `ValidateAllYAMLFiles` which uses the schema for validation.
- Dependencies were updated in `magefiles/go.mod` and `magefiles/go.sum`.

* Finished YAML validation pre-commit hook

- Streamlined the YAML validation process by consolidating it into a shared function.
- Improved error messaging for enhanced clarity.
- Established a new function, loadSchema, to facilitate schema loading and unmarshalling from a YAML file.
- Enhanced ValidateYAML to accommodate schema path input and extended support for directory-wide YAML file validation.
- Revised the validateAllYAML function to furnish comprehensive error messages and enhanced logging.
- Elevated error handling for YAML validation by providing informative error messages.
- Augmented the inspectAndValidate function to adeptly manage nested SubTTPSteps and validate referenced files.
- Implemented custom validation to ascertain the presence of the "name" property when "ttp" is declared in a step.

This commit amplifies the effectiveness of YAML file validation, ensuring strict adherence to the schema.
Introduces a pre-commit hook mechanism to preemptively thwart the commitment of non-conforming YAML files.

* Bug fixes and QOL improvements

- Fixed concurrency and infinite recursion bugs
- Resolved issue with having set -e set
- Optimized output to be useful

* Fix incorrectly marked regex type in TTPForge schema

* Refactor YAML validation logic from magefile.go to a new file schemaValidator.go.

- Fixed failures to catch problems in editsteps and args

* Fix incorrectly required item for EditStep
  • Loading branch information
l50 authored Sep 11, 2023
1 parent 0fada60 commit dbf997b
Show file tree
Hide file tree
Showing 6 changed files with 514 additions and 61 deletions.
50 changes: 50 additions & 0 deletions .hooks/validate-yaml.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/bash
# This script is a pre-commit hook that checks if the mage command is
# installed and if not, prompts the user to install it. If mage is
# installed, the script changes to the repository root and runs the
# `mage validateyaml` command for each staged YAML file. This command
# validates all committed YAML files against a predefined schema. If any
# validation fails, the commit is stopped and an error message is shown.

# Change to the repository root
cd "$(git rev-parse --show-toplevel)" || exit 1

# Determine the location of the mage binary
mage_bin=$(go env GOPATH)/bin/mage

# Check if mage is installed
if [[ ! -x "${mage_bin}" ]]; then
echo -e "mage is not installed\n"
echo -e "Please install mage by running the following command:\n"
echo -e "go install github.com/magefile/mage@latest\n"
exit 1
fi

# Get the list of staged files under ttps directory and ending with .yaml
staged_files=$(git diff --cached --name-only --diff-filter=AM | grep '^ttps/.*\.yaml$')

if [[ -z "$staged_files" ]]; then
echo "This commit has no TTPs that need to be validated."
exit 0
fi

echo "Files to validate: $staged_files"

# Iterate over each staged file and validate it
for file in $staged_files; do
# Run the mage validateyaml command for the staged YAML file
"${mage_bin}" validateyaml docs/ttpforge-spec.yaml "$file" || {
echo "Failed validation for: $file"
exit 1
}

# Catch the exit code of the last command
exit_status=$?

# If the exit code is not zero (i.e., the command failed),
# then stop the commit and show an error message
if [ $exit_status -ne 0 ]; then
echo "Failed to validate YAML file '$file' against the schema."
exit 1
fi
done
7 changes: 7 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,10 @@ repos:
language: script
entry: .hooks/shfmt.sh
files: \.sh$

- id: validate-yaml-files
name: Validate all committed YAML files against TTPForge schema
language: script
entry: .hooks/validate-yaml.sh
files: '\.yaml$'
require_serial: true
129 changes: 129 additions & 0 deletions docs/ttpforge-spec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
definitions:
TTP:
type: object
properties:
name:
type: string
description:
type: string
mitre:
$ref: "#/definitions/Mitre"
steps:
type: array
items:
oneOf:
- $ref: "#/definitions/SubTTPStep"
- $ref: "#/definitions/BasicStep"
- $ref: "#/definitions/EditStep"
args:
type: array
items:
$ref: "#/definitions/Spec"
required:
- name
- description
- steps

Mitre:
type: object
properties:
tactics:
type: array
items:
type: string
techniques:
type: array
items:
type: string
subtechniques:
type: array
items:
type: string

BasicStep:
type: object
properties:
name:
type: string
inline:
type: string
cleanup:
$ref: "#/definitions/CleanupAct"
args:
type: array
items:
type: string
required:
- name
- inline

CleanupAct:
type: object
properties:
inline:
type: string
required:
- inline

SubTTPStep:
type: object
properties:
name:
type: string
ttp:
type: string
args:
type: object
additionalProperties:
type: string
required:
- name
- ttp

EditStep:
type: object
properties:
name:
type: string
edit_file:
type: string
backup_file:
type: string
edits:
type: array
items:
$ref: "#/definitions/Edit"
required:
- name
- edit_file
- backup_file
- edits

Edit:
type: object
properties:
old:
type: string
new:
type: string
regexp:
type: boolean
required:
- old
- new

Spec:
type: object
properties:
name:
type: string
type:
type: string
default:
type: string
description:
type: string
required:
- name
- type
23 changes: 10 additions & 13 deletions magefiles/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,50 @@ go 1.21
toolchain go1.21.1

require (
github.com/go-playground/validator/v10 v10.15.3
github.com/l50/goutils/v2 v2.1.0
github.com/spf13/afero v1.9.5
github.com/spf13/viper v1.16.0
github.com/xeipuuv/gojsonschema v1.2.0
gopkg.in/yaml.v3 v3.0.1
)

require (
dario.cat/mergo v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
github.com/acomagu/bufpipe v1.0.4 // indirect
github.com/bitfield/script v0.22.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.4.1 // indirect
github.com/go-git/go-git/v5 v5.8.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/itchyny/gojq v0.12.13 // indirect
github.com/itchyny/timefmt-go v0.1.5 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/magefile/mage v1.15.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/otiai10/copy v1.12.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/sergi/go-diff v1.3.1 // indirect
github.com/skeema/knownhosts v1.2.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
mvdan.cc/sh/v3 v3.6.0 // indirect
)
Loading

0 comments on commit dbf997b

Please sign in to comment.