diff --git a/docs/content/en/docs/core-components/log.md b/docs/content/en/docs/core-components/log.md index 728dff02..2e93e4e5 100644 --- a/docs/content/en/docs/core-components/log.md +++ b/docs/content/en/docs/core-components/log.md @@ -72,9 +72,6 @@ To change logging for your SOARCA instance you can use the following environment |LOG_MODE |development \| production |If production is chosen the `LOG_GLOBAL_LEVEL` is used for all modules defaults to `production` |LOG_FILE_PATH |filepath |Path to the logfile you want to use for all logging. Defaults to `""` (empty string) |LOG_FORMAT |text \| json |The logging can be in plain text format or in JSON format. Defaults to `json` -|MQTT_BROKER | dns name or ip | The broker address for SOARCA to connect to, for communication with fins default is `localhost` -|MQTT_PORT | port | The broker address for SOARCA to connect to, for communication with fins default is `1883` -|ENABLE_FINS| true \| false | Enable fins in SOARCA defaults to `false` diff --git a/docs/content/en/docs/getting-started/_index.md b/docs/content/en/docs/getting-started/_index.md index 0629e48b..82a01ada 100644 --- a/docs/content/en/docs/getting-started/_index.md +++ b/docs/content/en/docs/getting-started/_index.md @@ -98,6 +98,7 @@ LOG_FORMAT: "json" ENABLE_FINS: false MQTT_BROKER: "localhost" MQTT_PORT: 1883 +VALIDATION_SCHEMA_URL: "" {{< /tab >}} {{< /tabpane >}} @@ -113,3 +114,23 @@ make build cp .env.example .env ./build/soarca ``` + +### Configuring SOARCA + +|variable |content |description +|---|---|---| +|PORT |port |Set the exposed port of SOARCA the default is `8080` +|DATABASE |true \| false | Set if you want to run with external database default is `false` +|MONGODB_URI |uri |Set the Mongo DB uri default is `mongodb://localhost:27017` +|DATABASE_NAME |name |Set the Mongo DB database name when using docker default is `soarca` +|DB_USERNAME |user |Set the Mongo DB database user when using docker default is `root` +|DB_PASSWORD |password |Set the Mongo DB database users password when using docker default is `rootpassword`. IT IS RECOMMENDED TO CHANGE THIS IN PRODUCTION! +|MAX_REPORTERS |number |Set the maximum number of downstream reporters default is `5` +|LOG_GLOBAL_LEVEL |[Log levels] |One of the specified log levels. Defaults to `info` +|LOG_MODE |development \| production |If production is chosen the `LOG_GLOBAL_LEVEL` is used for all modules defaults to `production` +|LOG_FILE_PATH |filepath |Path to the logfile you want to use for all logging. Defaults to `""` (empty string) +|LOG_FORMAT |text \| json |The logging can be in plain text format or in JSON format. Defaults to `json` +|MQTT_BROKER | dns name or ip | The broker address for SOARCA to connect to, for communication with fins default is `localhost` +|MQTT_PORT | port | The broker address for SOARCA to connect to, for communication with fins default is `1883` +|ENABLE_FINS| true \| false | Enable fins in SOARCA defaults to `false` +|VALIDATION_SCHEMA_URL|url| Set a custom validation schema to be used to validate playbooks defaul is `""` to use internal. NOTE: changing this heavily impacts performance. diff --git a/go.mod b/go.mod index fcea8330..e251c980 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/google/uuid v1.3.1 github.com/joho/godotenv v1.5.1 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 + github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 github.com/swaggo/files v1.0.1 diff --git a/go.sum b/go.sum index 09fd47f5..30f89bc6 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik= github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= @@ -104,6 +106,8 @@ github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUA github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/models/validator/schema.go b/models/validator/schema.go index be4b3f77..d9c8e272 100644 --- a/models/validator/schema.go +++ b/models/validator/schema.go @@ -1,15 +1,19 @@ package validator import ( + "embed" "encoding/json" "errors" + "io/fs" "reflect" "soarca/logger" "soarca/models/cacao" + "soarca/utils" + "strings" "github.com/go-playground/validator/v10" - jsonschema "github.com/santhosh-tekuri/jsonschema/v5" _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" + jsonschema "github.com/santhosh-tekuri/jsonschema/v6" ) type Empty struct{} @@ -17,7 +21,12 @@ type Empty struct{} var component = reflect.TypeOf(Empty{}).PkgPath() var log *logger.Log -var oca_cacao_schemas string = "https://raw.githubusercontent.com/opencybersecurityalliance/cacao-roaster/main/lib/cacao-json-schemas/schemas/playbook.json" +const ( + oca_cacao_schemas string = "./schemas/playbook.json" +) + +//go:embed schemas/* +var schemas embed.FS //var oasis_cacao_schemas string = "https://raw.githubusercontent.com/oasis-open/cacao-json-schemas/main/schemas/playbook.json" //var cyentific_cacao_schemas string = "https://raw.githubusercontent.com/cyentific-rni/cacao-json-schemas/cacao-v2.0-csd03/schemas/playbook.json" @@ -45,6 +54,52 @@ func UnmarshalJson[BodyType any](b *[]byte) (any, error) { return body, nil } +func validateWithLocalSchema(playbookToValidate map[string]interface{}) error { + + compiler := jsonschema.NewCompiler() + + err := fs.WalkDir(schemas, ".", func(path string, d fs.DirEntry, err error) error { + isFile := d.Type().IsRegular() + + if isFile { + content, _ := fs.ReadFile(schemas, path) + data, err := jsonschema.UnmarshalJSON(strings.NewReader(string(content))) + if err != nil { + return err + } + if err := compiler.AddResource(path, data); err != nil { + return err + } + } + return nil + }) + if err != nil { + log.Error(err) + return err + } + + sch, err := compiler.Compile(oca_cacao_schemas) + if err != nil { + return err + } + + err = sch.Validate(playbookToValidate) + return err +} + +func validateWithRemoteSchema(data map[string]interface{}, url string) error { + compiler := jsonschema.NewCompiler() + + sch, err := compiler.Compile(url) + if err != nil { + return err + } + if err := sch.Validate(data); err != nil { + return err + } + return nil +} + func IsValidCacaoJson(data []byte) error { var rawJson map[string]interface{} @@ -54,25 +109,18 @@ func IsValidCacaoJson(data []byte) error { version := rawJson["spec_version"] - compiler := jsonschema.NewCompiler() - compiler.Draft = jsonschema.Draft7 - - var sch *jsonschema.Schema - var err error switch version { case cacao.CACAO_VERSION_1: return errors.New("you submitted a cacao v1 playbook. at the moment, soarca only supports cacao v2 playbooks") case cacao.CACAO_VERSION_2: - sch, err = compiler.Compile(oca_cacao_schemas) - if err != nil { - return err + schemaUrl := utils.GetEnv("VALIDATION_SCHEMA_URL", "") + if schemaUrl != "" { + return validateWithRemoteSchema(rawJson, schemaUrl) + } else { + return validateWithLocalSchema(rawJson) } default: return errors.New("unsupported cacao version") } - if err := sch.Validate(rawJson); err != nil { - return err - } - return nil } diff --git a/models/validator/schemas/agent-target/agent-target.json b/models/validator/schemas/agent-target/agent-target.json new file mode 100644 index 00000000..b89612df --- /dev/null +++ b/models/validator/schemas/agent-target/agent-target.json @@ -0,0 +1,63 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "agent-target", + "description": "In a CACAO playbook, agents are the entities that execute commands (see section 5) on or against targets. Agents are stored in a dictionary where the ID is the key and the value is an 'agent-target' object (see section 10.1). Targets are stored in a dictionary where the ID is the key and the value is an 'agent-target' object (see section 10.1). Common properties for agents and targets are defined in section 7.1. \n\nAgents can involve either manual or automated processing. For example, an individual may process a command manually, while a firewall may process a command automatically. An agent and target type vocabulary is defined in section 7.2, and each agent and target type is further defined in the rest of the sections. Types include security infrastructure such as firewalls, routers, and threat intelligence platforms, as well as specific network addressable agents like URLs and IPv4/IPv6/MAC addresses. \n\nAgents and targets can use and refer to variables just like other parts of the playbook. For any agent or target property value, the producer may define a variable substitution such that the actual property value is determined at runtime based on the variable assigned to the agent or target. In Example 7.1, an agent is referenced within a workflow step, but the agent's actual values are based on variables (e.g., name, email, phone, location) instead of being hard-coded by the agent itself. \n\nEach object (agent or target) contains base properties that are common across all objects. These properties are defined in the following table. The ID for each object is stored as the key in the agent_definitions dictionary or the target_definitions dictionary.", + "type": "object", + "properties": { + "type": { + "$ref": "#/$defs/agent-target-type-ov", + "description": "The type of object being used. The value of this property SHOULD come from the 'agent-target-type-ov' vocabulary." + }, + "name": { + "type": "string", + "description": "The name that represents this object that is meant to be displayed in a user interface or captured in a log message. This property MUST be populated." + }, + "description": { + "type": "string", + "description": "More details, context, and possibly an explanation about this object. This property SHOULD be populated." + }, + "location": { + "$ref": "../data-types/civic-location.json", + "description": "Physical address information for this object." + }, + "agent_target_extensions": { + "minProperties": 1, + "type": "object", + "patternProperties": { + "^extension-definition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "type": "object" + } + }, + "description": "This property declares the extensions that are in use on this action or target and contains any of the properties and values that are to be used by that extension. \n\nThe key for each entry in the dictionary MUST be an 'identifier' (see section 10.10 for more information on identifiers) that uniquely identifies the extension. The value for each key is a JSON object that contains the structure as defined in the extension definition's schema property. The actual step extension definition is located in the 'extension_definitions' property found at the Playbook level." + } + }, + "required": [ + "type", + "name" + ], + "$defs": { + "agent-target-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "group", + "individual", + "location", + "organization", + "sector", + "http-api", + "linux", + "net-address", + "security-category", + "ssh" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/group.json b/models/validator/schemas/agent-target/group.json new file mode 100644 index 00000000..22b26770 --- /dev/null +++ b/models/validator/schemas/agent-target/group.json @@ -0,0 +1,27 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "group", + "description": "This type defines a group object and is used for commands that need to be processed or executed by a group. This object inherits the common agent properties. In addition to the inherited properties, this section defines the following additional property that is valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'group'.", + "enum": [ + "group" + ] + }, + "contact": { + "$ref": "../data-types/contact.json", + "description": "Contact information for this agent." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/http-api.json b/models/validator/schemas/agent-target/http-api.json new file mode 100644 index 00000000..c8944954 --- /dev/null +++ b/models/validator/schemas/agent-target/http-api.json @@ -0,0 +1,131 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "http-api", + "description": "This type defines an HTTP API object and is used for commands that need to be processed or executed by an HTTP API. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'http-api'.", + "enum": [ + "http-api" + ] + }, + "address": { + "type": "object", + "patternProperties": { + "^url$": { + "type": "array", + "items": { + "type": "string", + "pattern": "[(http(s)?):/(www.)?a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&//=]*)" + } + }, + "^l2mac$": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}$" + } + }, + "^ipv4$": { + "type": "array", + "items": { + "type": "string", + "pattern": "(\\b25[0-5]|\\b2[0-4][0-9]|\\b[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$" + } + }, + "^ipv6$": { + "type": "array", + "items": { + "type": "string", + "pattern": "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$" + } + }, + "^vlan$": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0, + "maximum": 4095 + } + }, + "^dname$": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "The key for each entry in the dictionary MUST be a 'string' that uniquely identifies one or more address types. The key(s) MUST be one of the following values 'dname' (domain name), 'ipv4', 'ipv6', 'l2mac', 'vlan', or 'url'. The dictionary value associated with each key MUST be a 'list' of 'string' that contains the corresponding address(es) for that particular key type." + }, + "port": { + "type": "string", + "description": "The TCP port number for the HTTP system. The default value is 80 based on standard port number services [PortNumbers].", + "default": "80" + }, + "authentication_info": { + "$ref": "../data-types/identifier.json", + "description": "This property contains an ID reference to a CACAO 'authentication-info' object that is stored at the Playbook level in the 'authentication_info_definitions' property. The ID MUST reference a CACAO 'authentication-info' object (see section 6)." + }, + "category": { + "type": "array", + "description": "One or more identified categories of security infrastructure types that this agent represents (see section 7.11.1). The value for this property SHOULD come from the 'security-category-type-ov' vocabulary.", + "items": { + "$ref": "#/$defs/security-category-type-ov" + }, + "minItems": 1 + } + } + } + ], + "required": [ + "address" + ], + "$defs": { + "security-category-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "aaa", + "analytics", + "caldera", + "content-gateway", + "desktop", + "endpoint", + "firewall", + "handset", + "ids", + "ips", + "kali", + "manx", + "orchestrator", + "os-linux", + "os-mac", + "os-windows", + "redcanary-atomicred", + "ragdoll", + "router", + "sandcat", + "server", + "siem", + "switch", + "ticketing", + "tip", + "wireless" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/individual.json b/models/validator/schemas/agent-target/individual.json new file mode 100644 index 00000000..8363964b --- /dev/null +++ b/models/validator/schemas/agent-target/individual.json @@ -0,0 +1,27 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "individual", + "description": "This type defines an individual object and is used for commands that need to be processed or executed by an individual. This object inherits the common agent properties. In addition to the inherited properties, this section defines the following additional property that is valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'individual'.", + "enum": [ + "individual" + ] + }, + "contact": { + "$ref": "../data-types/contact.json", + "description": "Contact information for this agent." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/linux.json b/models/validator/schemas/agent-target/linux.json new file mode 100644 index 00000000..8d2e072c --- /dev/null +++ b/models/validator/schemas/agent-target/linux.json @@ -0,0 +1,130 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "linux", + "description": "This type defines a Linux system object and is used for commands that need to be processed or executed by a Linux system. In addition to the inherited properties, this section defines four additional specific properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'linux'.", + "enum": [ + "linux" + ] + }, + "address": { + "type": "object", + "patternProperties": { + "^url$": { + "type": "array", + "items": { + "type": "string", + "pattern": "[(http(s)?):/(www.)?a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&//=]*)" + } + }, + "^l2mac$": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}$" + } + }, + "^ipv4$": { + "type": "array", + "items": { + "type": "string", + "pattern": "(\\b25[0-5]|\\b2[0-4][0-9]|\\b[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$" + } + }, + "^ipv6$": { + "type": "array", + "items": { + "type": "string", + "pattern": "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$" + } + }, + "^vlan$": { + "type": "array", + "items": { + "type": "number", + "minimum": 0, + "maximum": 4095 + } + }, + "^dname$": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "The key for each entry in the dictionary MUST be a string that uniquely identifies one or more address types. The key(s) MUST be one of the following values 'dname' (domain name), 'ipv4', 'ipv6', 'l2mac', 'vlan', or 'url'. The dictionary value associated with each key MUST be a 'list' of 'string' that contains the corresponding address(es) for that particular key type." + }, + "port": { + "type": "string", + "description": "The TCP port number for the Linux system." + }, + "authentication_info": { + "$ref": "../data-types/identifier.json", + "description": "This property contains an ID reference to a CACAO 'authentication-info' object that is stored at the playbook level in the 'authentication_info_definitions' property. The ID MUST reference a CACAO 'authentication-info' object (see section 6)." + }, + "category": { + "type": "array", + "description": "One or more identified categories of security infrastructure types that this agent represents (see section 7.11.1). The value for this property SHOULD come from the 'security-category-type-ov' vocabulary.", + "items": { + "$ref": "#/$defs/security-category-type-ov" + }, + "minItems": 1 + } + } + } + ], + "required": [ + "address" + ], + "$defs": { + "security-category-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "aaa", + "analytics", + "caldera", + "content-gateway", + "desktop", + "endpoint", + "firewall", + "handset", + "ids", + "ips", + "kali", + "manx", + "orchestrator", + "os-linux", + "os-mac", + "os-windows", + "redcanary-atomicred", + "ragdoll", + "router", + "sandcat", + "server", + "siem", + "switch", + "ticketing", + "tip", + "wireless" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/location.json b/models/validator/schemas/agent-target/location.json new file mode 100644 index 00000000..a083698b --- /dev/null +++ b/models/validator/schemas/agent-target/location.json @@ -0,0 +1,31 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "location", + "description": "This type defines a location object and is used for commands that need to be processed or executed by or at a location. This object inherits the common agent properties. In addition to the inherited properties, this section defines the following additional property that is valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'location'.", + "enum": [ + "location" + ] + }, + "logical": { + "type": "array", + "description": "An optional list of logical location names as defined by the playbook creator (e.g., wiring closet, network segment, room number, etc.).", + "items": { + "type": "string" + }, + "minItems": 1 + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/net-address.json b/models/validator/schemas/agent-target/net-address.json new file mode 100644 index 00000000..187f6b05 --- /dev/null +++ b/models/validator/schemas/agent-target/net-address.json @@ -0,0 +1,126 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "net-address", + "description": "This type defines a network address object and is used for commands that need to be processed or executed by a device at a network address. In addition to the inherited properties, this section defines three additional specific properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'net-address'.", + "enum": [ + "net-address" + ] + }, + "address": { + "type": "object", + "patternProperties": { + "^url$": { + "type": "array", + "items": { + "type": "string", + "pattern": "[(http(s)?):/(www.)?a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&//=]*)" + } + }, + "^l2mac$": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}$" + } + }, + "^ipv4$": { + "type": "array", + "items": { + "type": "string", + "pattern": "(\\b25[0-5]|\\b2[0-4][0-9]|\\b[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$" + } + }, + "^ipv6$": { + "type": "array", + "items": { + "type": "string", + "pattern": "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$" + } + }, + "^vlan$": { + "type": "array", + "items": { + "type": "number", + "minimum": 0, + "maximum": 4095 + } + }, + "^dname$": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "The key for each entry in the dictionary MUST be a 'string' that uniquely identifies one or more address types. The key(s) MUST be one of the following values 'dname' (domain name), 'ipv4', 'ipv6', 'l2mac', 'vlan', or 'url'. The dictionary value associated with each key MUST be a 'list' of 'string' that contains the corresponding address(es) for that particular key type." + }, + "authentication_info": { + "$ref": "../data-types/identifier.json", + "description": "This property contains an ID reference to a CACAO 'authentication-info' object that is stored at the playbook level in the 'authentication_info_definitions' property. The ID MUST reference a CACAO 'authentication-info' object (see section 6)." + }, + "category": { + "type": "array", + "description": "One or more identified categories of security infrastructure types that this agent represents (see section 7.11.1). \n\nThe value for this property SHOULD come from the 'security-category-type-ov' vocabulary.", + "items": { + "$ref": "#/$defs/security-category-type-ov" + }, + "minItems": 1 + } + } + } + ], + "required": [ + "address" + ], + "$defs": { + "security-category-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "aaa", + "analytics", + "caldera", + "content-gateway", + "desktop", + "endpoint", + "firewall", + "handset", + "ids", + "ips", + "kali", + "manx", + "orchestrator", + "os-linux", + "os-mac", + "os-windows", + "redcanary-atomicred", + "ragdoll", + "router", + "sandcat", + "server", + "siem", + "switch", + "ticketing", + "tip", + "wireless" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/organization.json b/models/validator/schemas/agent-target/organization.json new file mode 100644 index 00000000..06b01000 --- /dev/null +++ b/models/validator/schemas/agent-target/organization.json @@ -0,0 +1,27 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "organization", + "description": "This type defines an organization object and is used for commands that need to be processed or executed by an organization. This object inherits the common agent properties. In addition to the inherited properties, this section defines the following additional property that is valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'organization'.", + "enum": [ + "organization" + ] + }, + "contact": { + "$ref": "../data-types/contact.json", + "description": "Contact information for this agent." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/sector.json b/models/validator/schemas/agent-target/sector.json new file mode 100644 index 00000000..086b1055 --- /dev/null +++ b/models/validator/schemas/agent-target/sector.json @@ -0,0 +1,94 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "sector", + "description": "This type defines a sector object and is used for commands that need to be processed or executed by a sector. This object inherits the common agent properties. In addition to the inherited properties, this section defines the following additional property that is valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'sector'.", + "enum": [ + "sector" + ] + }, + "sector": { + "$ref": "#/$defs/industry-sector-ov", + "description": "The values this property SHOULD come from the 'industry-sector-ov' vocabulary, see section 7.7.1." + } + } + } + ], + "required": [ + "sector" + ], + "$defs": { + "industry-sector-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "aerospace", + "aviation", + "agriculture", + "automotive", + "biotechnology", + "chemical", + "commercial", + "consulting", + "construction", + "cosmetics", + "critical-infrastructure", + "dams", + "defense", + "education", + "emergency-services", + "energy", + "non-renewable-energy", + "renewable-energy", + "media", + "financial", + "food", + "gambling", + "government", + "local-government", + "national-government", + "regional-government", + "public-services", + "healthcare", + "information-communications-technology", + "electronics-hardware", + "software", + "telecommunications", + "legal-services", + "lodging", + "manufacturing", + "maritime", + "metals", + "mining", + "non-profit", + "humanitarian-aid", + "human-rights", + "nuclear", + "petroleum", + "pharmaceuticals", + "research", + "transportation", + "logistics-shipping", + "utilities", + "video-game", + "water" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/security-category.json b/models/validator/schemas/agent-target/security-category.json new file mode 100644 index 00000000..9cb348be --- /dev/null +++ b/models/validator/schemas/agent-target/security-category.json @@ -0,0 +1,74 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "security-category", + "description": "This type defines a security (infrastructure) category object and is used for commands that need to be processed or executed by a piece of security infrastructure. In addition to the inherited properties, this section defines the following additional property that is valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'security-category'.", + "enum": [ + "security-category" + ] + }, + "category": { + "type": "array", + "description": "One or more identified categories of security infrastructure types that this agent represents. A product instantiation may include one or more security infrastructure types as hints to assist in describing the agent features most likely required by a playbook step or playbook. \n\nThe values for this property SHOULD come from the 'security-category-type-ov' vocabulary.", + "items": { + "$ref": "#/$defs/security-category-type-ov" + }, + "minItems": 1 + } + } + } + ], + "required": [ + "category" + ], + "$defs": { + "security-category-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "aaa", + "analytics", + "caldera", + "content-gateway", + "desktop", + "endpoint", + "firewall", + "handset", + "ids", + "ips", + "kali", + "manx", + "orchestrator", + "os-linux", + "os-mac", + "os-windows", + "redcanary-atomicred", + "ragdoll", + "router", + "sandcat", + "server", + "siem", + "switch", + "ticketing", + "tip", + "wireless" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/agent-target/ssh.json b/models/validator/schemas/agent-target/ssh.json new file mode 100644 index 00000000..e87d6725 --- /dev/null +++ b/models/validator/schemas/agent-target/ssh.json @@ -0,0 +1,131 @@ +{ + "$id": "agent-target", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ssh", + "description": "This type defines a SSH CLI object and is used for commands that need to be processed or executed by an SSH CLI. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "agent-target.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'ssh'.", + "enum": [ + "ssh" + ] + }, + "address": { + "type": "object", + "patternProperties": { + "^url$": { + "type": "array", + "items": { + "type": "string", + "pattern": "[(http(s)?):/(www.)?a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&//=]*)" + } + }, + "^l2mac$": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}$" + } + }, + "^ipv4$": { + "type": "array", + "items": { + "type": "string", + "pattern": "(\\b25[0-5]|\\b2[0-4][0-9]|\\b[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$" + } + }, + "^ipv6$": { + "type": "array", + "items": { + "type": "string", + "pattern": "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$" + } + }, + "^vlan$": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0, + "maximum": 4095 + } + }, + "^dname$": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": " The key for each entry in the dictionary MUST be a 'string' that uniquely identifies one or more address types. The key(s) MUST be one of the following values 'dname' (domain name), 'ipv4', 'ipv6', 'l2mac', 'vlan', or 'url'. The dictionary value associated with each key MUST be a 'list' of 'string' that contains the corresponding address(es) for that particular key type." + }, + "port": { + "type": "string", + "description": "The TCP port number for the SSH service. The default value is 22 based on standard port number services [PortNumbers].", + "default": "22" + }, + "authentication_info": { + "$ref": "../data-types/identifier.json", + "description": "This property contains an ID reference to a CACAO 'authentication-info' object that is stored at the playbook level in the 'authentication_info_definitions' property. The ID MUST reference a CACAO 'authentication-info' object (see section 6)." + }, + "category": { + "type": "array", + "description": "One or more identified categories of security infrastructure types that this agent represents (see section 7.11.1). \n\nThe value for this property SHOULD come from the 'security-category-type-ov' vocabulary", + "items": { + "$ref": "#/$defs/security-category-type-ov" + }, + "minItems": 1 + } + } + } + ], + "required": [ + "address" + ], + "$defs": { + "security-category-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "aaa", + "analytics", + "caldera", + "content-gateway", + "desktop", + "endpoint", + "firewall", + "handset", + "ids", + "ips", + "kali", + "manx", + "orchestrator", + "os-linux", + "os-mac", + "os-windows", + "redcanary-atomicred", + "ragdoll", + "router", + "sandcat", + "server", + "siem", + "switch", + "ticketing", + "tip", + "wireless" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/authentication-info/authentication-info.json b/models/validator/schemas/authentication-info/authentication-info.json new file mode 100644 index 00000000..cd51771b --- /dev/null +++ b/models/validator/schemas/authentication-info/authentication-info.json @@ -0,0 +1,51 @@ +{ + "$id": "authentication-info", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "authentication-info", + "description": "In a CACAO playbook, authentication information is used by agents and targets when they need to authenticate against a resource. Authentication information is stored in a dictionary where the ID is the key and the value is an authentication-info object (see section 10.2). Common properties for an authentication information object are defined in section 6.1. \n\nAuthentication information can use and refer to variables just like other parts of the playbook. For any authentication information property value, the producer may define a variable substitution such that the actual property value is determined at runtime based on the variable assigned to the authentication information. In Example 6.1, authentication information is referenced within an agent, but the authentication information's actual values are based on variables instead of being hard-coded in the data itself. It is generally best practice to always use variables for authentication information. Each authentication information object contains base properties that are common across all objects. \n\nThese properties are defined in the following table. The ID for each object is stored as the key in the 'authentication_info_definitions' dictionary at the Playbook level.", + "type": "object", + "properties": { + "type": { + "$ref": "#/$defs/authentication-info-type-ov", + "description": "The type of object being used. The value of this property SHOULD come from the 'authentication-info-type-ov' vocabulary." + }, + "name": { + "type": "string", + "description": "The name that represents this object that is meant to be displayed in a user interface or captured in a log message. This property SHOULD be populated." + }, + "description": { + "type": "string", + "description": "More details, context, and possibly an explanation about this object." + }, + "authentication_info_extensions": { + "minProperties": 1, + "type": "object", + "patternProperties": { + "^extension-definition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "type": "object" + } + }, + "description": "This property declares the extensions that are in use on this authentication information object and contains any of the properties and values that are to be used by that extension. \n\nThe key for each entry in the dictionary MUST be an 'identifier' (see section 9.9 for more information on identifiers) that uniquely identifies the extension. The value for each key is a JSON object that contains the structure as defined in the extension definition's schema property. The actual step extension definition is located in the 'extension_definitions' property found at the Playbook level." + } + }, + "required": [ + "type" + ], + "$defs": { + "authentication-info-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "http-basic", + "oauth2", + "user-auth" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/authentication-info/http-basic.json b/models/validator/schemas/authentication-info/http-basic.json new file mode 100644 index 00000000..8340464e --- /dev/null +++ b/models/validator/schemas/authentication-info/http-basic.json @@ -0,0 +1,38 @@ +{ + "$id": "authentication-info", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "http-basic", + "description": "This type defines the HTTP basic authentication information object and is used by agents and targets when performing HTTP basic authentication. This object inherits all of the authentication information common properties (see section 6.1). In addition to the inherited properties, this section defines the following additional properties that are valid for this type. If the 'kms' and 'kms_key_identifier' properties are used the 'user_id' and 'password' properties MUST NOT be populated.", + "allOf": [ + { + "$ref": "authentication-info.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'http-basic'.", + "enum": [ + "http-basic" + ] + }, + "user_id": { + "type": "string", + "description": "The user_id property used in HTTP Basic authentication as defined by [RFC7617]." + }, + "password": { + "type": "string", + "description": "The password property used in HTTP Basic authentication as defined by [RFC7617]. This value SHOULD be passed in via a variable." + }, + "kms": { + "type": "boolean", + "description": "If this property is 'true' the key material associated with this authentication information is stored in a key management store and the 'kms_key_identifier' property contains the identifier used to look up the key material associated with the 'kms_key_identifier'. \n\nIf this property is set to true then the value of the 'kms_key_identifier' property MUST be defined and the value of the 'password' property MUST be ignored." + }, + "kms_key_identifier": { + "type": "string", + "description": "This property contains the key identifier for the authentication information value stored in a key management service (KMS) used by the orchestration system executing the playbook. \n\nThe specific KMS used by the orchestration system is out of scope of this specification. \n\nIf this property is defined then the 'kms' property MUST be set to 'true'." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/authentication-info/oauth2.json b/models/validator/schemas/authentication-info/oauth2.json new file mode 100644 index 00000000..7d3cdfb2 --- /dev/null +++ b/models/validator/schemas/authentication-info/oauth2.json @@ -0,0 +1,42 @@ +{ + "$id": "authentication-info", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "oauth2", + "description": "This type defines the Oauth2 authentication information object and is used by agents and targets when performing oauth2 authentication. This object inherits all of the authentication information common properties (see section 6.1). In addition to the inherited properties, this section defines the following additional properties that are valid for this type. If the 'kms' and 'kms_key_identifier' properties are used the 'token' property MUST NOT be populated.", + "allOf": [ + { + "$ref": "authentication-info.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'oauth2'.", + "enum": [ + "oauth2" + ] + }, + "oauth_header": { + "type": "string", + "description": "The OAuth header used in OAuth authentication as defined in section 3.5.1 of [RFC5849] and [RFC6750]." + }, + "token": { + "type": "string", + "description": "The bearer token used in HTTP Bearer Token authentication as defined by [RFC6749] and [RFC6750]. This value SHOULD be passed in via a variable." + }, + "kms": { + "type": "boolean", + "description": "If this property is 'true' the key material associated with this authentication information is stored in a key management store and the 'kms_key_identifier' property contains the identifier used to look up the key material associated with the 'kms_key_identifier'. \n\nIf this property is set to 'true' then the value of the 'kms_key_identifier' property MUST be defined and the value of the 'token' property MUST be ignored." + }, + "kms_key_identifier": { + "type": "string", + "description": "This property contains the key identifier for the authentication information value stored in a key management service (KMS) used by the orchestration system executing the playbook. \n\nThe specific KMS used by the orchestration system is out of scope of this specification. \n\nIf this property is defined then the 'kms' property MUST be set to 'true'." + } + } + } + ], + "required": [ + "oauth_header", + "token" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/authentication-info/user-auth.json b/models/validator/schemas/authentication-info/user-auth.json new file mode 100644 index 00000000..200820f0 --- /dev/null +++ b/models/validator/schemas/authentication-info/user-auth.json @@ -0,0 +1,38 @@ +{ + "$id": "authentication-info", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "user-auth", + "description": "This type defines a generic username / password authentication information object and is used by agents and targets when performing authentication. This object inherits all of the authentication information common properties (see section 6.1). In addition to the inherited properties, this section defines the following additional properties that are valid for this type. If the 'kms' and 'kms_key_identifier' properties are used the 'username' and 'password' properties MUST NOT be populated.", + "allOf": [ + { + "$ref": "authentication-info.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'user-auth'.", + "enum": [ + "user-auth" + ] + }, + "username": { + "type": "string", + "description": "A username for this authentication." + }, + "password": { + "type": "string", + "description": "The password for this authentication. This value SHOULD be passed in via a variable." + }, + "kms": { + "type": "boolean", + "description": "If this property is 'true' the key material associated with this authentication information is stored in a key management store and the 'kms_key_identifier' property contains the identifier used to look up the key material associated with the 'kms_key_identifier'. \n\nIf this property is set to 'true' then the value of the 'kms_key_identifier' property MUST be defined and the value of the 'password' property MUST be ignored." + }, + "kms_key_identifier": { + "type": "string", + "description": "This property contains the key identifier for the authentication information value stored in a key management service (KMS) used by the orchestration system executing the playbook. \n\nThe specific KMS used by the orchestration system is out of scope of this specification. \n\nIf this property is defined then the 'kms' property MUST be set to 'true'." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/bash.json b/models/validator/schemas/commands/bash.json new file mode 100644 index 00000000..5e2101bc --- /dev/null +++ b/models/validator/schemas/commands/bash.json @@ -0,0 +1,32 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "bash", + "description": "The bash command represents a command that is intended to be processed via a shell without a login/remote connection. In addition to the inherited properties, this section defines the following additional properties that are valid for this type. Either the 'command' property or the 'command_b64' property MUST be present.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'bash'.", + "enum": [ + "bash" + ] + }, + "command": { + "type": "string", + "description": "A simple string-based command. A command that has quoted values or other characters including spacing or carriage returns that are significant and thus need to be escaped SHOULD use the 'command_b64' property instead. \n\nThe value of this property if present MUST be a valid bash command." + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A complex command that can not be encoded as a simple string and thus MUST be base64 encoded (see section 4 of [RFC 4648]). The value of this property if present MUST be a valid bash command." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/caldera-cmd.json b/models/validator/schemas/commands/caldera-cmd.json new file mode 100644 index 00000000..e7616741 --- /dev/null +++ b/models/validator/schemas/commands/caldera-cmd.json @@ -0,0 +1,32 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "caldera-cmd", + "description": "The caldera command represents a command that is intended to be processed via an attack orchestration system to attack or simulate an attack against a target. In addition to the inherited properties, this section defines the following additional properties that are valid for this type. Either the 'command' property or the 'command_b64' property MUST be present.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'caldera-cmd'.", + "enum": [ + "caldera-cmd" + ] + }, + "command": { + "type": "string", + "description": "A simple string-based reference to a caldera command (see example 5.4). \n\nThe value of this property if present MUST be a valid caldera command reference." + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A complex command that can not be encoded as a simple string and thus MUST be base64 encoded (see section 4 of [RFC 4648]). \n\nThe value of this property MUST be a valid caldera command." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/command-data.json b/models/validator/schemas/commands/command-data.json new file mode 100644 index 00000000..6aac09d9 --- /dev/null +++ b/models/validator/schemas/commands/command-data.json @@ -0,0 +1,99 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "command-data", + "description": "The CACAO command object ('command-data') contains detailed information about the commands that are to be executed automatically or manually as part of an action step (see section 4.5). Each command listed in an action step may be of a different command type, however, all commands listed in a single step MUST be processed or executed by all of the agents defined in that step. \n\nCommands can make use of variables just like other parts of the playbook. \n\nEach command object contains base properties that are common across all commands. These common properties are defined in the following table.", + "type": "object", + "allOf": [ + { + "properties": { + "type": { + "$ref": "#/$defs/command-type-ov", + "description": "The type of command being used. The value of this property SHOULD come from the 'command-type-ov' vocabulary." + }, + "description": { + "type": "string", + "description": "A description of this command." + }, + "version": { + "type": "string", + "description": "The version of the command type being used. If no version is specified then the most current version of the command type SHOULD be used." + }, + "playbook_activity": { + "$ref": "#/$defs/playbook-activity-type-ov", + "description": "A meta data description of the playbook activity that the command provides that enables summarization at the playbook level of all activities defined within the playbook. This property SHOULD be populated. \n\nThe value for this property SHOULD come from the 'playbook-activity-type-ov' vocabulary." + }, + "external_references": { + "type": "array", + "items": { + "$ref": "./../data-types/external-reference.json" + }, + "description": "A list of external references for this command." + } + } + } + ], + "required": [ + "type" + ], + "$defs": { + "command-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "manual", + "bash", + "caldera-cmd", + "elastic", + "http-api", + "jupyter", + "kestrel", + "openc2-http", + "powershell", + "sigma", + "ssh", + "yara" + ] + } + ] + }, + "playbook-activity-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "compose-content", + "deliver-content", + "identify-audience", + "identify-channel", + "scan-system", + "match-indicator", + "analyze-collected-data", + "identify-indicators", + "scan-vulnerabilities", + "configure-systems", + "restrict-access", + "disconnect-system", + "eliminate-risk", + "revert-system", + "restore-data", + "restore-capabilities", + "map-network", + "identify-steps", + "step-sequence", + "prepare-engagement", + "execute-operation", + "analyze-engagement-results" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/commands/elastic.json b/models/validator/schemas/commands/elastic.json new file mode 100644 index 00000000..86bc269f --- /dev/null +++ b/models/validator/schemas/commands/elastic.json @@ -0,0 +1,31 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "elastic", + "description": "The elastic command represents a command that is intended to be processed via an elasticsearch query. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'elastic'.", + "enum": [ + "elastic" + ] + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A base64 encoded (see section 4 of [RFC 4648]) elastic command. \n\nThe value of this 'command_b64' property MUST be a valid sigma command." + } + } + } + ], + "required": [ + "command_b64" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/http-api.json b/models/validator/schemas/commands/http-api.json new file mode 100644 index 00000000..2dc8d17e --- /dev/null +++ b/models/validator/schemas/commands/http-api.json @@ -0,0 +1,49 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "http-api", + "description": "The HTTP API command represents a command that is intended to be processed via an HTTP API. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'http-api'.", + "enum": [ + "http-api" + ] + }, + "command": { + "type": "string", + "description": "An HTTP start line that contains three elements, an HTTP method, a request target, and the HTTP version (see https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages). For example: \n\n'GET /api1/getObject?id=1234 HTTP/1.1' \n\n'POST /api1/newObject HTTP/1.1'" + }, + "headers": { + "type": "object", + "description": "This property contains any required HTTP headers. \n\nThe key for each entry in the dictionary MUST be a string that uniquely identifies the header. The value for each key MUST be a 'list' of 'string'.", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "content": { + "type": "string", + "description": "A simple string-based content (payload/body) for a given method (e.g., 'POST' and 'PUT')." + }, + "content_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A complex or binary content (payload/body) for a given method (e.g., 'POST' and 'PUT') that can not be encoded as a simple string and thus MUST be base64 encoded (see section 4 of [RFC 4648])." + } + } + } + ], + "required": [ + "command" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/jupyter.json b/models/validator/schemas/commands/jupyter.json new file mode 100644 index 00000000..1cfe388a --- /dev/null +++ b/models/validator/schemas/commands/jupyter.json @@ -0,0 +1,31 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "jupyter", + "description": "The jupyter notebook command represents a command that is intended to be processed via a jupyter notebook processor. In addition to the inherited properties, this section defines the following additional property that is valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'jupyter'.", + "enum": [ + "jupyter" + ] + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A base64 encoded (see section 4 of [RFC 4648]) sigma command. \n\nThe value of this 'command_b64' property MUST be a valid sigma command." + } + } + } + ], + "required": [ + "command_b64" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/kestrel.json b/models/validator/schemas/commands/kestrel.json new file mode 100644 index 00000000..a7393dd7 --- /dev/null +++ b/models/validator/schemas/commands/kestrel.json @@ -0,0 +1,31 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "kestrel", + "description": "The kestrel command represents a command that is intended to be processed via a kestrel processor for threat hunting. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'kestrel'.", + "enum": [ + "kestrel" + ] + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A base64 encoded (see section 4 of [RFC 4648]) kestrel command. \n\nThe value of this 'command_b64' property MUST be a valid kestrel command." + } + } + } + ], + "required": [ + "command_b64" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/manual.json b/models/validator/schemas/commands/manual.json new file mode 100644 index 00000000..42f359ab --- /dev/null +++ b/models/validator/schemas/commands/manual.json @@ -0,0 +1,32 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "manual", + "description": "The manual command represents a command that is intended to be processed by a human or a system that acts on behalf of a human. In addition to the inherited properties, this section defines the following additional properties that are valid for this type. Either the 'command' property or the 'command_b64' property MUST be present.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'manual'.", + "enum": [ + "manual" + ] + }, + "command": { + "type": "string", + "description": "A simple string-based command. Any command that has quoted values or other characters including spacing or carriage returns that are significant and thus need to be escaped SHOULD use the 'command_b64' property instead. \n\nThe value of this property if present MUST be a valid manual command." + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A complex command that can not be encoded as a simple string and thus MUST be base64 encoded (see section 4 of [RFC 4648]). \n\nThe value of this property if present MUST be a valid manual command." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/openc2-http.json b/models/validator/schemas/commands/openc2-http.json new file mode 100644 index 00000000..f1a4b08a --- /dev/null +++ b/models/validator/schemas/commands/openc2-http.json @@ -0,0 +1,46 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "openc2-http", + "description": "The openc2 command represents a command that is intended to be processed via an openc2 processor via an HTTP agent/target. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'openc2-http'.", + "enum": [ + "openc2-http" + ] + }, + "command": { + "type": "string", + "description": "The OpenC2 HTTP command uses the HTTP transport. As such this property MUST contain an HTTP start line that contains three elements, an HTTP method, a request target, and the HTTP version (see https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages). \n\nFor this command the HTTP method MUST be 'POST'. For example: \n\n'POST /api1/newObject HTTP/1.1'" + }, + "content_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "An OpenC2 command that is base64 encoded (see section 4 of [RFC 4648])." + }, + "headers": { + "type": "object", + "description": "This property contains any required HTTP headers. \n\nThe key for each entry in the dictionary MUST be a 'string' that uniquely identifies the header. The value for each key MUST be a 'list' of 'string'.", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + ], + "required": [ + "command", + "content_b64" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/powershell.json b/models/validator/schemas/commands/powershell.json new file mode 100644 index 00000000..668f0602 --- /dev/null +++ b/models/validator/schemas/commands/powershell.json @@ -0,0 +1,32 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "powershell", + "description": "The powershell command represents a command that is intended to be processed via a powershell processor. In addition to the inherited properties, this section defines the following additional properties that are valid for this type. Either the 'command' property or the 'command_b64' property MUST be present.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'powershell'.", + "enum": [ + "powershell" + ] + }, + "command": { + "type": "string", + "description": "A simple string-based powershell command. A command that has quoted values or other characters including spacing or carriage returns that are significant and thus need to be escaped SHOULD use the 'command_b64' property instead. \n\nThe value of this property if present MUST be a valid powershell command." + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A complex command that can not be encoded as a simple string and thus MUST be base64 encoded (see section 4 of [RFC 4648]). \n\nThe value of this property if present MUST be a valid powershell command or powershell script." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/sigma.json b/models/validator/schemas/commands/sigma.json new file mode 100644 index 00000000..b5b6dd83 --- /dev/null +++ b/models/validator/schemas/commands/sigma.json @@ -0,0 +1,31 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "sigma", + "description": "The sigma command represents a command that is intended to be processed via a sigma processor. In addition to the inherited properties, this section defines the following additional property that is valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'sigma'.", + "enum": [ + "sigma" + ] + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A base64 encoded (see section 4 of [RFC 4648]) sigma command. \n\nThe value of this 'command_b64' property MUST be a valid sigma command." + } + } + } + ], + "required": [ + "command_b64" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/ssh.json b/models/validator/schemas/commands/ssh.json new file mode 100644 index 00000000..e2272940 --- /dev/null +++ b/models/validator/schemas/commands/ssh.json @@ -0,0 +1,32 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ssh", + "description": "The SSH command represents a command that is intended to be processed via an SSH connection. In addition to the inherited properties, this section defines the following additional properties that are valid for this type. Either the 'command' property or the 'command_b64' property MUST be present.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'ssh'.", + "enum": [ + "ssh" + ] + }, + "command": { + "type": "string", + "description": "A simple string-based SSH command. A command that has quoted values or other characters including spacing or carriage returns that are significant and thus need to be escaped SHOULD use the 'command_b64' property instead. \n\nThe value of this property if present MUST be a valid ssh command." + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A complex command that can not be encoded as a simple string and thus MUST be base64 encoded (see section 4 of [RFC 4648]). \n\nThe value of this property if present MUST be a valid ssh command." + } + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/commands/yara.json b/models/validator/schemas/commands/yara.json new file mode 100644 index 00000000..95c1d5a1 --- /dev/null +++ b/models/validator/schemas/commands/yara.json @@ -0,0 +1,31 @@ +{ + "$id": "commands", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "yara", + "description": "The yara command represents a command that is intended to be processed via a yara processor. In addition to the inherited properties, this section defines the following additional property that is valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "./command-data.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'yara'.", + "enum": [ + "yara" + ] + }, + "command_b64": { + "type": "string", + "contentEncoding": "base64", + "description": "A base64 encoded (see section 4 of [RFC 4648]) yara command. \n\nThe value of this 'command_b64' property MUST be a valid yara command." + } + } + } + ], + "required": [ + "command_b64" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/data-markings/data-marking.json b/models/validator/schemas/data-markings/data-marking.json new file mode 100644 index 00000000..69360ce4 --- /dev/null +++ b/models/validator/schemas/data-markings/data-marking.json @@ -0,0 +1,87 @@ +{ + "$id": "data-markings", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "data-marking", + "description": "CACAO data marking definition objects contain detailed information about a specific data marking. Data markings typically represent handling or sharing requirements and are applied via the markings property in a playbook. \n\nData marking objects MUST NOT be versioned because it would allow for indirect changes to the markings on a playbook. For example, if a statement marking definition is changed from 'Reuse Allowed' to 'Reuse Prohibited', all playbooks marked with that statement marking definition would effectively have an updated marking without being updated themselves. Instead, in this example a new statement marking definition with the new text should be created and the marked objects updated to point to the new data marking object. \n\nPlaybooks may be marked with multiple marking statements. In other words, the same playbook can be marked with both a statement saying 'Copyright 2020' and a statement saying, 'Terms of use are ...' and both statements apply. This specification does not define rules for how multiple markings applied to the same object should be interpreted. \n\nEach data marking object contains base properties that are common across all data markings. These common properties are defined in the following table.", + "type": "object", + "properties": { + "type": { + "$ref": "#/$defs/data-marking-type-enum", + "description": "The type of data marking being used. \n\nThe value for this property MUST come from the 'data-marking-type-enum' enumeration." + }, + "id": { + "$ref": "../data-types/identifier.json", + "description": "A value that uniquely identifies the data marking definition." + }, + "name": { + "type": "string", + "description": "A name used to identify this data marking." + }, + "description": { + "type": "string", + "description": "More details, context, and possibly an explanation about what this data marking does and tries to accomplish." + }, + "created_by": { + "$ref": "../data-types/identifier.json", + "description": "An ID that represents the entity that created this data marking. The ID MUST represent a STIX 2.1+ identity object." + }, + "created": { + "$ref": "../data-types/timestamp.json", + "description": "The time at which this data marking was originally created. The creator can use any time it deems most appropriate as the time the data marking was created, but it MUST be precise to the nearest millisecond (exactly three digits after the decimal place in seconds). The created property MUST NOT be changed." + }, + "revoked": { + "type": "boolean", + "description": "A boolean that identifies if the creator deems that this data marking is no longer valid. The default value is 'false'. Processing of data that has been previously shared with an associated data marking that is subsequently revoked is unspecified and dependent on the implementation of the consuming software." + }, + "valid_from": { + "$ref": "../data-types/timestamp.json", + "description": "The time from which this data marking is considered valid. \n\nIf omitted, the data marking is valid at all times or until the timestamp defined by valid_until. \n\nIf the revoked property is 'true' then this property MUST be ignored." + }, + "valid_until": { + "$ref": "../data-types/timestamp.json", + "description": "The time at which this data marking SHOULD no longer be considered a valid marking definition. \n\nIf the valid_until property is omitted, then there is no constraint on the latest time for which the data marking is valid. \n\nThis property MUST be greater than the timestamp in the valid_from property if the valid_from property is defined. \n\nIf the revoked property is 'true' then this property MUST be ignored." + }, + "labels": { + "type": "array", + "description": "A set of terms, labels, or tags associated with this data marking. The values may be user, organization, or trust-group defined and their meaning is outside the scope of this specification.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "external_references": { + "type": "array", + "description": "An list of external references for this data marking.", + "items": { + "$ref": "../data-types/external-reference.json" + }, + "minItems": 1 + }, + "marking_extensions": { + "minProperties": 1, + "type": "object", + "patternProperties": { + "^extension-definition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "type": "object" + } + }, + "description": "This property declares the extensions that are in use on this data marking and contains any of the properties and values that are to be used by that extension. \n\nThe key for each entry in the dictionary MUST be an 'identifier' (see section 10.10 for more information on identifiers) that uniquely identifies the extension. The value for each key is a JSON object that contains the structure as defined in the extension definition's schema property. The actual step extension definition is located in the 'extension_definitions' property found at the Playbook level." + } + }, + "required": [ + "type", + "id", + "created_by", + "created" + ], + "$defs": { + "data-marking-type-enum": { + "type": "string", + "enum": [ + "marking-statement", + "marking-tlp", + "marking-iep" + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/data-markings/marking-iep.json b/models/validator/schemas/data-markings/marking-iep.json new file mode 100644 index 00000000..0dd8e5dd --- /dev/null +++ b/models/validator/schemas/data-markings/marking-iep.json @@ -0,0 +1,95 @@ +{ + "$id": "data-markings", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "marking-iep", + "description": "The IEP marking object defines the representation of a FIRST IEP marking statement. For more information about the properties from the IEP specification, please refer to that document [IEP].", + "type": "object", + "allOf": [ + { + "$ref": "data-marking.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'marking-iep'.", + "enum": [ + "marking-iep" + ] + }, + "name": { + "type": "string", + "description": "The name of the IEP policy." + }, + "description": { + "type": "string", + "description": "See IEP Specification [IEP]." + }, + "tlp": { + "type": "string", + "description": "TLPv1. See IEP Specification [IEP]." + }, + "iep_version": { + "type": "integer", + "description": "See IEP Specification [IEP]." + }, + "start_date": { + "$ref": "../data-types/timestamp.json", + "description": "See IEP Specification [IEP]." + }, + "end_date": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "../data-types/timestamp.json" + } + ], + "description": "See IEP Specification [IEP]." + }, + "encrypt_in_transit": { + "type": "string", + "description": "See IEP Specification [IEP]." + }, + "permitted_actions": { + "type": "string", + "description": "See IEP Specification [IEP]." + }, + "affected_party_notifications": { + "type": "string", + "description": "See IEP Specification [IEP]." + }, + "attribution": { + "type": "string", + "description": "See IEP Specification [IEP]." + }, + "unmodified_resale": { + "type": "string", + "description": "See IEP Specification [IEP]." + }, + "external_references": { + "type": "array", + "items": { + "type": "string" + }, + "description": "See IEP Specification [IEP]." + } + } + } + ], + "required": [ + "name", + "description", + "tlp", + "iep_version", + "start_date", + "end_date", + "encrypt_in_transit", + "permitted_actions", + "affected_party_notifications", + "attribution", + "unmodified_resale", + "external_references" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/data-markings/marking-statement.json b/models/validator/schemas/data-markings/marking-statement.json new file mode 100644 index 00000000..9c07efca --- /dev/null +++ b/models/validator/schemas/data-markings/marking-statement.json @@ -0,0 +1,30 @@ +{ + "$id": "data-markings", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "marking-statement", + "description": "The statement marking object defines the representation of a textual marking statement (e.g., copyright, terms of use, etc.). Statement markings are generally not machine-readable, and this specification does not define any behavior or actions based on their values.", + "type": "object", + "allOf": [ + { + "$ref": "data-marking.json" + }, + { + "properties": { + "type": { + "type": "string", + "enum": [ + "marking-statement" + ], + "description": "The value of this property MUST be 'marking-statement'." + }, + "statement": { + "type": "string", + "description": "A statement (e.g., copyright, terms of use) applied to the content marked by this marking definition." + } + } + } + ], + "required": [ + "statement" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/data-markings/marking-tlp.json b/models/validator/schemas/data-markings/marking-tlp.json new file mode 100644 index 00000000..235e1f99 --- /dev/null +++ b/models/validator/schemas/data-markings/marking-tlp.json @@ -0,0 +1,37 @@ +{ + "$id": "data-markings", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "marking-tlp", + "description": "The TLP marking object defines the representation of a FIRST TLP V2 marking statement.", + "type": "object", + "allOf": [ + { + "$ref": "data-marking.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'marking-tlp'.", + "enum": [ + "marking-tlp" + ] + }, + "tlpv2_level": { + "type": "string", + "enum": [ + "TLP:RED", + "TLP:AMBER", + "TLP:AMBER+STRICT", + "TLP:GREEN", + "TLP:CLEAR" + ], + "description": "The value of this property is the name of the TLP V2 level as defined by FIRST [TLP]. The value MUST be one of the following: 'TLP:RED', 'TLP:AMBER', 'TLP:AMBER+STRICT', 'TLP:GREEN', 'TLP:CLEAR'" + } + } + } + ], + "required": [ + "tlpv2_level" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/data-types/civic-location.json b/models/validator/schemas/data-types/civic-location.json new file mode 100644 index 00000000..86ab5425 --- /dev/null +++ b/models/validator/schemas/data-types/civic-location.json @@ -0,0 +1,97 @@ +{ + "$id": "data-types", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "civic-location", + "description": "The 'civic-location' data type captures civic location information and uses the JSON object type [RFC8259] for serialization. Implementations need to be mindful when including physical address information and GPS information into the same civic location to ensure that they reference the same actual physical location. However, in the event that the physical address information and the GPS information do not match, then the physical address information SHOULD be considered correct.", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "A name for this location." + }, + "description": { + "type": "string", + "description": "A detailed description about this location." + }, + "building_details": { + "type": "string", + "description": "Additional details about the location within a building including things like floor, room, etc." + }, + "network_details": { + "type": "string", + "description": "Additional details about this network location including things like wiring closet, rack number, rack location, and VLANs." + }, + "region": { + "$ref": "#/$defs/region-enum", + "description": "The geographical region for this location. \n\nThe value for this property MUST come from the region-enum enumeration (see section 10.4.1)." + }, + "country": { + "type": "string", + "description": "The country for this location. This property MUST contain a valid ISO 3166-1 ALPHA-2 Code [ISO3166-1]." + }, + "administrative_area": { + "type": "string", + "description": "The state, province, or other sub-national administrative area for this location. \n\nThis property SHOULD contain a valid ISO 3166-2 Code [ISO3166-2]." + }, + "city": { + "type": "string", + "description": "The city for this location." + }, + "street_address": { + "type": "string", + "description": "The street address for this location. This property includes all aspects or parts of the street address. For example, some addresses may have multiple lines including a mailstop or apartment number." + }, + "postal_code": { + "type": "string", + "description": "The postal code for this location." + }, + "latitude": { + "type": "string", + "description": "The GPS latitude of the location in decimal degrees. Positive numbers describe latitudes north of the equator, and negative numbers describe latitudes south of the equator. The value of this property MUST be less than or equal to 90.0 and greater than -90.0 (i.e., 90.0 >= x > -90.0). \n\nIf the longitude property is present, this property MUST be present. \n\nNOTE: Some systems like Google Maps have the following rules. 'Latitude ranges between -90 and 90 degrees, inclusive. Values above or below this range will be clamped to the range [-90, 90]. This means that if the value specified is less than -90, it will be set to -90. And if the value is greater than 90, it will be set to 90.' [Google Maps]" + }, + "longitude": { + "type": "string", + "description": "The GPS longitude of the location in decimal degrees. Positive numbers describe longitudes east of the prime meridian and negative numbers describe longitudes west of the prime meridian. The value of this property MUST be less than or equal to 180.0 and a value that is greater than -180.0 (i.e., 180.0 >= x > -180.0). \n\nIf the latitude property is present, this property MUST be present. \n\nNOTE: Some systems like Google Maps have the following rules. 'Longitude ranges between -180 and 180 degrees, inclusive. Values above or below this range will be wrapped so that they fall within the range. For example, a value of -190 will be converted to 170. A value of 190 will be converted to -170. This reflects the fact that longitudes wrap around the globe.' [Google Maps]" + }, + "precision": { + "type": "string", + "description": "Defines the precision of the coordinates specified by the 'latitude' and 'longitude' properties. This is measured in meters. The actual agent may be anywhere up to precision meters from the defined point. \n\nIf this property is not present, then the precision is unspecified. \n\nIf this property is present, the 'latitude' and 'longitude' properties MUST be present." + } + }, + "$defs": { + "region-enum": { + "type": "string", + "enum": [ + "africa", + "eastern-africa", + "middle-africa", + "northern-africa", + "southern-africa", + "western-africa", + "americas", + "caribbean", + "central-america", + "latin-america-caribbean", + "northern-america", + "south-america", + "asia", + "central-asia", + "eastern-asia", + "southern-asia", + "south-eastern-asia", + "western-asia", + "europe", + "eastern-europe", + "northern-europe", + "southern-europe", + "western-europe", + "oceania", + "antarctica", + "australia-new-zealand", + "melanesia", + "micronesia", + "polynesia" + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/data-types/contact.json b/models/validator/schemas/data-types/contact.json new file mode 100644 index 00000000..c2b66d90 --- /dev/null +++ b/models/validator/schemas/data-types/contact.json @@ -0,0 +1,31 @@ +{ + "$id": "data-types", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "contact", + "description": "The 'contact' information data type captures general contact information and uses the JSON object type [RFC8259] for serialization.", + "type": "object", + "properties": { + "email": { + "type": "object", + "patternProperties": { + "^[a-zA-Z0-9_-]{0,250}$": { + "type": "string" + } + }, + "description": "An email address for this contact. \n\nThe key for each entry in the dictionary MUST be a 'string' that uniquely identifies the contact type (e.g., the keys could be things like 'work', 'home', 'personal', etc). The value for each key MUST be a 'string'." + }, + "phone": { + "type": "object", + "patternProperties": { + "^[a-zA-Z0-9_-]{0,250}$": { + "type": "string" + } + }, + "description": "A phone number for this contact. \n\nThe key for each entry in the dictionary MUST be a 'string' that uniquely identifies the type (e.g., the keys could be things like 'work', 'home', 'personal', etc). The value for each key MUST be a 'string'." + }, + "contact_details": { + "type": "string", + "description": "Additional contact information." + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/data-types/external-reference.json b/models/validator/schemas/data-types/external-reference.json new file mode 100644 index 00000000..64ff9f7c --- /dev/null +++ b/models/validator/schemas/data-types/external-reference.json @@ -0,0 +1,36 @@ +{ + "$id": "data-types", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "external-reference", + "description": "The 'external-reference' data type captures the location of information represented outside of a CACAO playbook and uses the JSON object type [RFC8259] for serialization. For example, a playbook could reference external documentation about a specific piece of malware that the playbook is trying to address. In addition to the name properties at least one of the following properties MUST be present: 'description', 'source', 'url', 'external_id', or 'reference_id'.", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the author or title of the source of this external reference." + }, + "description": { + "type": "string", + "description": "A detailed description of this external reference." + }, + "source": { + "type": "string", + "description": "A textual citation of this source. The citation source MAY use a standard citation format like Chicago, MLA, APA, or similar style." + }, + "url": { + "type": "string", + "description": "A URL [RFC3986] for this external reference." + }, + "external_id": { + "type": "string", + "description": "An identifier used by the source to reference this content. Some organizations give names or numbers to content that they publish. This property would capture that information to help ensure that a consumer is being referred to the correct content." + }, + "reference_id": { + "type": "string", + "description": "An identifier that represents the data that this content is referring to. This property is especially useful when referencing content that already exists in a graph dataset or can be referenced via some ID. When referencing STIX content, this would be the STIX-based UUID." + } + }, + "required": [ + "name" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/data-types/identifier.json b/models/validator/schemas/data-types/identifier.json new file mode 100644 index 00000000..ac21c6f0 --- /dev/null +++ b/models/validator/schemas/data-types/identifier.json @@ -0,0 +1,8 @@ +{ + "$id": "data-types", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "identifier", + "description": "The identifier data type represents an RFC 4122-compliant UUID [RFC4122] and uses the JSON string type [RFC8259] for serialization. \n\nAn identifier uniquely identifies a CACAO object. All identifiers MUST follow the form object-type--UUID, where object-type is the exact value (all type names are lowercase strings by definition) from the type property of the object being identified and where the UUID MUST be an RFC 4122-compliant UUID [RFC4122]. \n\nThe UUID part of the identifier MUST be unique across all objects regardless of the type identified by the object-type prefix. Meaning, a producer MUST NOT reuse the UUID portion of the identifier for objects of different types. \n\nAll CACAO objects SHOULD use UUIDv4 for the UUID portion of the identifier. A CACAO playbook object MAY use UUIDv5 for the UUID portion of the identifier. All CACAO step objects MUST use UUIDv4. \n\nUsing a UUIDv5 for the playbook MAY allow producers and consumers using the same namespace and contributing properties to generate the same identifier for that playbook. When using UUIDv5 the UUID portion of the UUIDv5-based identifier SHOULD be generated according to the following rules: \n\nThe namespace SHOULD be 'aa7caf3a-d55a-4e9a-b34e-056215fba56a'. \n\nThe value of the name portion SHOULD be a series of properties from the object that will ensure a globally unique identifier and those properties SHOULD be stringified according to the JSON Canonicalization Scheme [RFC8785] to ensure a canonical representation of the JSON data. \n\nThe contributing properties to the playbook object's UUIDv5 name portion SHOULD be the name and playbook_types properties. \n\nProducers not following these rules MUST NOT use a namespace of 'aa7caf3a-d55a-4e9a-b34e-056215fba56a'", + "type": "string", + "pattern": "^[a-z][a-z0-9-]+[a-z0-9]--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" +} \ No newline at end of file diff --git a/models/validator/schemas/data-types/playbook-processing-summary.json b/models/validator/schemas/data-types/playbook-processing-summary.json new file mode 100644 index 00000000..f559d6b2 --- /dev/null +++ b/models/validator/schemas/data-types/playbook-processing-summary.json @@ -0,0 +1,53 @@ +{ + "$id": "data-types", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "playbook-processing-summary", + "description": "The 'playbook-processing-summary' data type represents the major processing features and functionality of a playbook and contains a summarized list of the processing features that can be implemented for a specific playbook and is defined at the playbook metadata level. This is done to help implementations identify the concepts and features used within a specific playbook without having to parse the entire playbook.", + "type": "object", + "properties": { + "manual_playbook": { + "type": "boolean", + "description": "This type of playbook contains only manual commands and simple text-based descriptions or tasks." + }, + "external_playbooks": { + "type": "boolean", + "description": "See section 4.6." + }, + "parallel_processing": { + "type": "boolean", + "description": "See section 4.7." + }, + "if_logic": { + "type": "boolean", + "description": "See section 4.8." + }, + "while_logic": { + "type": "boolean", + "description": "See section 4.9." + }, + "switch_logic": { + "type": "boolean", + "description": "See section 4.10." + }, + "temporal_logic": { + "type": "boolean", + "description": "See section 4.1 'delay' and 'timeout' properties." + }, + "data_markings": { + "type": "boolean", + "description": "See section 2.4 and section 9." + }, + "digital_signatures": { + "type": "boolean", + "description": "See section 10.15." + }, + "countersigned_signatures": { + "type": "boolean", + "description": "See section 10.15." + }, + "extensions": { + "type": "boolean", + "description": "See section 8." + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/data-types/signature.json b/models/validator/schemas/data-types/signature.json new file mode 100644 index 00000000..c41c301c --- /dev/null +++ b/models/validator/schemas/data-types/signature.json @@ -0,0 +1,160 @@ +{ + "$id": "data-types", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "signature", + "description": "The 'signature' data type captures the actual digital signature and meta-data about the signature and uses the JSON object type [RFC8259] for serialization. See section Appendix A for a detailed example. \n\n* One of the following properties MUST be populated, 'public_key' (preferred), 'public_cert_chain', 'cert_url', or 'thumbprint'.", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'jss'.", + "enum": [ + "jss" + ] + }, + "id": { + "$ref": "identifier.json", + "description": "A value that uniquely identifies the signature. All signatures with the same ID are considered different versions of the same signature and the version of the signature is identified by its 'modified' property." + }, + "created_by": { + "$ref": "identifier.json", + "description": "An ID that represents the entity that created this signature. The ID MUST represent a STIX 2.1+ identity object." + }, + "created": { + "$ref": "timestamp.json", + "description": "The time at which this signature was originally created. The creator can use any time it deems most appropriate as the time the signature was created, but it MUST be precise to the nearest millisecond (exactly three digits after the decimal place in seconds). The created property MUST NOT be changed when creating a new version of the signature." + }, + "modified": { + "$ref": "timestamp.json", + "description": "The time that this particular version of the signature was last modified. The creator can use any time it deems most appropriate as the time that this version of the signature was modified, but it MUST be precise to the nearest millisecond (exactly three digits after the decimal place in seconds). The modified property MUST be later than or equal to the value of the created property. If the created and 'modified' properties are the same, then this is the first version of the signature." + }, + "revoked": { + "type": "boolean", + "description": "A boolean that identifies if the signature creator deems that this signature is no longer valid. The default value is 'false'.", + "default": false + }, + "signee": { + "type": "string", + "description": "An unstructured string value for the name of the entity or organization that produced this signature." + }, + "valid_from": { + "$ref": "timestamp.json", + "description": "The time from which this signature is considered valid. \n\nIf omitted, the signature is valid at all times or until the timestamp defined by 'valid_until'. If the revoked property is 'true' then this property MUST be ignored." + }, + "valid_until": { + "$ref": "timestamp.json", + "description": "The time at which this signature should no longer be considered valid. \n\nIf the 'valid_until' property is omitted, then there is no constraint on the latest time for which the signature is valid. \n\nThis property MUST be greater than the timestamp in the 'valid_from' property if the 'valid_from' property is defined. If the 'revoked' property is true then this property MUST be ignored." + }, + "related_to": { + "$ref": "identifier.json", + "description": "A value that can identify the original playbook object that was signed with this signature. The value of this property MUST be a CACAO playbook id. If the signature is detached from the original playbook object then this property MUST be populated." + }, + "related_version": { + "$ref": "timestamp.json", + "description": "A value that can identify the version of the original playbook object that was signed with this signature. The value of this property MUST be the modified 'timestamp' from the CACAO playbook that this signature is for." + }, + "hash_algorithm": { + "type": "string", + "description": "This property identifies the hashing algorithm, as defined by IANA, that was used to hash the JCS version of the full playbook object (Playbook Object + X.jss Signature) and is a case-sensitive ASCII string. As of this writing, implementations SHOULD use 'sha-256' or 'sha-512' but MAY use any current and widely accepted hashing algorithm that is defined in the IANA registry. \n\nThe actual signing process, defined in the 'algorithm' property, sometimes uses an internal hashing algorithm inside the signing process itself, this property MAY identify the same hashing algorithm as the signing process or MAY identify a different hashing algorithm." + }, + "algorithm": { + "$ref": "#/$defs/signature-algorithm-type-ov", + "description": "This property identifies the algorithm that was used to sign the playbook and is a case-sensitive ASCII string. \n\nThe value for this property SHOULD come from the 'signature-algorithm-type-ov' vocabulary and SHOULD be a current and widely accepted quantum safe algorithm, but MAY be any currently accepted safe algorithm. \n\nAt the time of this writing quantum safe algorithms could come from those defined in XMSS [RFC 8391] section 5.3 or LMS [RFC 8554] section 5.1 and other algorithms could come from those defined in JWA [RFC 7518] section 3.1 or [RFC 8037] section 3.1. \n\nWhile JWA [RFC7518] section 3.1 defines the following symmetric algorithms: 'HS256', 'HS384', and 'HS512' these algorithms SHOULD NOT be used, as CACAO playbooks are intended to be shared across system and organizational boundaries. If one of these three symmetric algorithms or some other symmetric algorithm is used, then the sharing and transmission of those keys is out of scope for this specification." + }, + "public_key": { + "type": "string", + "description": "This property contains a PEM encoded public key without the header and footer for the algorithm selected in the 'algorithm' property." + }, + "public_cert_chain": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "This property contains a public key certificate for the algorithm selected in the algorithm property and MUST follow the requirements defined in section 4.7 of [RFC7517] as quoted here. This property 'contains a chain (X.509 certificate chain) of one or more PKIX certificates [RFC5280]. The certificate chain is represented as a JSON array of certificate value strings. Each string in the array is a base64-encoded (Section 4 of [RFC4648] -- not base64URL.encoded) DER [ITU.X690.1994] PKIX certificate value. The PKIX certificate containing the key value MUST be the first certificate. This MAY be followed by additional certificates, with each subsequent certificate being the one used to certify the previous one. The key in the first certificate MUST match the public key.' This property is called 'x5c' in section 4.7 of [RFC7517]." + }, + "cert_url": { + "type": "string", + "description": "This property contains a URI [RFC3986] that refers to a resource for an X.509 public key certificate or certificate chain [RFC5280] for the algorithm selected in the 'algorithm' property and MUST follow the requirements defined in section 4.6 of [RFC7517] as quoted here. 'The identified resource MUST provide a representation of the certificate or certificate chain that conforms to RFC 5280 [RFC5280] in PEM-encoded form, with each certificate delimited as specified in section 7.1 of RFC 4945 [RFC4945]. The key in the first certificate MUST match the public key. The protocol used to acquire the resource MUST provide integrity protection; an HTTP GET request to retrieve the certificate MUST use TLS [RFC2818] [RFC5246]; the identity of the server MUST be validated, as per section 6 of RFC 6125 [RFC6125].' This property is called 'x5u' in section 4.6 of [RFC7517]." + }, + "thumbprint": { + "type": "string", + "description": "This property contains a fingerprint of a public key or public key certificate for the algorithm selected in the 'algorithm' property and MUST follow the requirements defined in section 4.9 of [RFC7517] as quoted here. This property 'is a base64URL.encoded SHA-256 thumbprint (a.k.a. digest, X.509 certificate SHA-256 thumbprint) of the DER encoding of an X.509 certificate [RFC5280]. Note that certificate thumbprints are also sometimes known as certificate fingerprints. The key in the certificate MUST match the public key.' This property is called 'x5t#S256' in section 4.9 of [RFC7517]." + }, + "value": { + "type": "string", + "description": "A base64URL.encoded signature that was created using the signature algorithm defined in the 'algorithm' property and a key. In pseudo code it is defined as: \n\nbase64URL.encode(sign(algorithm, key, hash(jcs())))." + }, + "signature": { + "$ref": "signature.json", + "description": "This property enables a signature to be countersigned, meaning a signature can be signed by another signature." + } + }, + "required": [ + "type", + "id", + "created", + "modified", + "signee", + "related_to", + "related_version", + "hash_algorithm", + "algorithm", + "value" + ], + "oneOf": [ + { + "required": [ + "public_key" + ] + }, + { + "required": [ + "public_cert_chain" + ] + }, + { + "required": [ + "cert_url" + ] + }, + { + "required": [ + "thumbprint" + ] + } + ], + "$defs": { + "signature-algorithm-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "RS256", + "RS384", + "RS512", + "ES256", + "ES384", + "ES512", + "PS256", + "PS384", + "PS512", + "Ed25519", + "Ed448", + "XMSS-SHA2_10_256", + "XMSS-SHA2_16_256", + "XMSS-SHA2_20_256", + "LMS_SHA256_M32_H5", + "LMS_SHA256_M32_H10", + "LMS_SHA256_M32_H15", + "LMS_SHA256_M32_H20", + "LMS_SHA256_M32_H25" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/data-types/timestamp.json b/models/validator/schemas/data-types/timestamp.json new file mode 100644 index 00000000..f01dc5cd --- /dev/null +++ b/models/validator/schemas/data-types/timestamp.json @@ -0,0 +1,8 @@ +{ + "$id": "data-types", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "timestamp", + "description": "The 'timestamp' data type represents dates and times and uses the JSON string type [RFC8259] for serialization. The timestamp data MUST be a valid RFC 3339-formatted timestamp [RFC3339] using the format yyyy-mm-ddThh:mm:ss[.s+]Z where the 's+' represents 1 or more sub-second values. The brackets denote that sub-second precision is optional, and that if no digits are provided, the decimal place MUST NOT be present. The timestamp MUST be represented in the UTC+0 timezone and MUST use the 'Z' designation to indicate this. Additional requirements may be defined where this data type is used.", + "type": "string", + "pattern": "^[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?Z$" +} \ No newline at end of file diff --git a/models/validator/schemas/data-types/variable.json b/models/validator/schemas/data-types/variable.json new file mode 100644 index 00000000..02e23008 --- /dev/null +++ b/models/validator/schemas/data-types/variable.json @@ -0,0 +1,65 @@ +{ + "$id": "data-types", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "variable", + "description": "Variables can be defined and then used as the playbook is executed. Variables are stored in a dictionary where the key is the name of the variable and the value is a variable data type. Variables can represent stateful elements that may need to be captured to allow for the successful execution of the playbook. All playbook variables are mutable unless identified as a constant. \n\nIn addition to the rules for all dictionary keys, variable names: \n\nMUST be unique within the contextual scope they are declared. \n\nMUST be prefixed and suffixed with __ (two underscore characters) for both declaration and use. \n\nMUST contain the keyword ':value' when using the variable (e.g., __ipaddress__:value). \n\nMUST include the double underscore '__' for the variable name prefix and suffix (a total of four characters) as part of the 250 ASCII character length limit. \n\nMUST start with a letter after the variable prefix __. \n\nAre case-sensitive (age, Age and AGE are three different variables) but SHOULD be lowercase. \n\nThe scope of a variable is determined by where the variable is declared. A variable may be defined globally for the entire playbook or locally within a workflow step. Variables are scoped to the object they are defined in, and any object that is used or referenced by that object. A specific variable can only be defined once, however, a variable can be assigned and used in the object where it is defined or in any object used or referenced by that object (e.g., a playbook variable can be assigned at the playbook level but also reassigned a different value within a workflow step). \n\nVariables are referenced by using the key name from the dictionary with a suffix (keyword) of ':value'. For example, if you had a variable in the dictionary called '__ip_addresses__', one could reference this and use it in a playbook by using '__ip_addresses__:value'. Variables MAY be passed to and from external playbooks provided that system supports passing of arguments when the system function is invoked or returns its results. \n\nThe 'variable' data type captures variable information and uses the JSON object type [RFC8259] for serialization.", + "type": "object", + "properties": { + "type": { + "$ref": "#/$defs/variable-type-ov", + "description": "The type of variable being used. The value for this property SHOULD come from the 'variable-type-ov' vocabulary." + }, + "description": { + "type": "string", + "description": "An detailed description of this variable." + }, + "value": { + "type": [ + "string", + "null" + ], + "description": "The value MUST be defined as one of the following JSON types: a string value, a number or boolean encoded as a JSON string, an empty string \"\", the special JSON NULL value, or a JSON object. \n\nNOTE: An empty string is NOT equivalent to a JSON NULL value. An empty string means the value is known to be empty. A value of NULL means the value is unknown or undefined." + }, + "constant": { + "type": "boolean", + "description": "This property defines if this variable is immutable. If true, the variable is immutable and MUST NOT be changed. If false, the variable is mutable and can be updated later on in the playbook. The default value is 'false'. If this property is not present then the value is 'false'.", + "default": false + }, + "external": { + "type": "boolean", + "description": "This property only applies to playbook scoped variables. \n\nWhen set to 'true' the variable declaration defines that the variable's initial value is passed into the playbook from a calling context. \n\nWhen set to 'false' or omitted, the variable is defined within the playbook." + } + }, + "required": [ + "type" + ], + "$defs": { + "variable-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "bool", + "dictionary", + "float", + "hexstring", + "integer", + "ipv4-addr", + "ipv6-addr", + "long", + "mac-addr", + "hash", + "md5-hash", + "sha256-hash", + "string", + "uri", + "uuid" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/extension-definition/extension-definition.json b/models/validator/schemas/extension-definition/extension-definition.json new file mode 100644 index 00000000..bc8cf66b --- /dev/null +++ b/models/validator/schemas/extension-definition/extension-definition.json @@ -0,0 +1,50 @@ +{ + "$id": "extension-definition", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "extension-definition", + "description": "The CACAO extension object allows a playbook producer to define detailed information about the extensions that are in use in a playbook that they created. In a playbook, extensions are stored in a dictionary where the ID is the key and the extension definition object is the value. Workflow steps, agents, data markings and playbooks themselves can use extensions by referencing their IDs. \n\nExtensions can use and refer to all objects that may be used in other parts of a playbook including variables and constants just like other parts of the playbook. While the extension's name and description are optional, they are encouraged and producers SHOULD populate them \n\n Requirements for Extension Properties: \n\nA CACAO playbook MAY have any number of Extensions containing one or more properties. \n\nExtension property names MUST be in ASCII and MUST only contain the characters a-z (lowercase ASCII), 0-9, and underscore (_). \n\nExtension property names MUST have a minimum length of 3 ASCII characters. \n\nExtension property names MUST be no longer than 250 ASCII characters in length. \n\nExtension properties SHOULD only be used when there are no existing properties defined by the CACAO playbook specification that fulfills that need.", + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "extension-definition" + ], + "description": "The value of this property MUST be 'extension-definition'." + }, + "name": { + "type": "string", + "description": "A name used to identify this extension for display purposes during execution, development or troubleshooting." + }, + "description": { + "type": "string", + "description": "More details, context, and possibly an explanation about what this extension does and accomplishes. \n\nWhile the extension's description is optional, it is encouraged that producers SHOULD populate the property. \n\nNOTE: The schema property is the normative definition of the extension, and this property, if present, is for documentation purposes only." + }, + "created_by": { + "$ref": "../data-types/identifier.json", + "description": "An ID that represents the entity that created this extension. The ID MUST represent a STIX 2.1+ identity object." + }, + "schema": { + "type": "string", + "description": "The normative definition of the extension, either as a URL or as text explaining the definition. \n\nA URL SHOULD point to a JSON schema or a location that contains information about the schema." + }, + "version": { + "type": "string", + "description": "The version of this extension. Producers of playbook extensions are encouraged to follow standard semantic versioning procedures where the version number follows the pattern, MAJOR.MINOR.PATCH [SemVer]. This will allow consumers to distinguish between the three different levels of compatibility typically identified by such versioning strings." + }, + "external_references": { + "type": "array", + "items": { + "$ref": "./../data-types/external-reference.json" + }, + "description": "A list of external references for this extension." + } + }, + "required": [ + "type", + "name", + "created_by", + "schema", + "version" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/playbook.json b/models/validator/schemas/playbook.json new file mode 100644 index 00000000..a2745a27 --- /dev/null +++ b/models/validator/schemas/playbook.json @@ -0,0 +1,460 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "playbook", + "description": "CACAO playbooks are made up of six parts playbook metadata, the workflow logic, a list of object definitions used in the workflow logic (agents and targets), a list of extensions, a list of data markings, and a list of any digital signatures. Playbooks MAY refer to other playbooks in the workflow, similar to how programs refer to function calls or modules that comprise the program. The definition and normative requirements for all data types listed in the property table below and other property tables in this document can be found in Section 10.", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'playbook'.", + "enum": [ + "playbook" + ] + }, + "spec_version": { + "type": "string", + "description": "The version of the specification used to represent this playbook. The value of this property MUST be 'cacao-2.0' to represent the version of this specification.", + "enum": [ + "cacao-2.0" + ] + }, + "id": { + "$ref": "data-types/identifier.json", + "description": "A value that uniquely identifies the playbook. All playbooks with the same id are considered different versions of the same playbook and the version of the playbook is identified by its modified property." + }, + "name": { + "type": "string", + "description": "A name for this playbook. Playbook names often follow a naming convention that is unique within an organization, community, or trust group and as such this name SHOULD be unique." + }, + "description": { + "type": "string", + "description": "More details, context, and possibly an explanation about what this playbook does and tries to accomplish. Producers SHOULD populate this property." + }, + "playbook_types": { + "type": "array", + "description": "A list of playbook types that specifies the operational roles that this playbook addresses. This property SHOULD be populated. \n\nThe values for this property SHOULD come from the 'playbook-type-ov' vocabulary (see section 3.1.1).", + "items": { + "$ref": "#/$defs/playbook-type-ov" + } + }, + "playbook_activities": { + "type": "array", + "description": "A list of activities pertaining to the playbook. This property SHOULD be populated. If the playbook_types property is populated and comes from the playbook-type-ov then this property MUST have at least one assigned activity. \n\nThis property allows an author to define more detailed descriptions for the various activities that a playbook performs. This property provides a much richer and verbose method to describe all aspects of a playbook than just the playbook_types property. \n\nThe values for this property SHOULD come from the 'playbook-activity-type-ov' vocabulary (see section 3.1.2). \n\nEach listed activity MUST be reflected in a CACAO workflow step object and that object MUST be included in the workflow property.", + "items": { + "$ref": "#/$defs/playbook-activity-type-ov" + }, + "minItems": 1 + }, + "playbook_processing_summary": { + "$ref": "data-types/playbook-processing-summary.json", + "description": "This property contains a summarized list of processing features that are defined within this playbook. This property enables the content of a playbook to be assessed without requiring the entire content to be parsed or understood. See section 10.14." + }, + "created_by": { + "$ref": "data-types/identifier.json", + "description": "An ID that represents the entity that created this playbook. The ID MUST represent a STIX 2.1+ identity object." + }, + "created": { + "$ref": "data-types/timestamp.json", + "description": "The time at which this playbook was originally created. The creator can use any time it deems most appropriate as the time the playbook was created, but it MUST be given to the nearest millisecond (exactly three digits after the decimal place in seconds). The created property MUST NOT be changed when creating a new version of the object." + }, + "modified": { + "$ref": "data-types/timestamp.json", + "description": "The time that this particular version of the playbook was last modified. The creator can use any time it deems most appropriate as the time that this version of the playbook was modified, but it MUST be given to the nearest millisecond (exactly three digits after the decimal place in seconds). The modified property MUST be later than or equal to the value of the created property. If created and modified properties are the same, then this is the first version of the playbook." + }, + "revoked": { + "type": "boolean", + "description": "A boolean that identifies if the playbook creator deems that this playbook is no longer valid. The default value is 'false'." + }, + "valid_from": { + "$ref": "data-types/timestamp.json", + "description": "The time from which this playbook is considered valid and the workflow steps that it contains can be executed. More detailed information about time frames MAY be applied in the workflow. \n\nIf omitted, the playbook is valid at all times or until the timestamp defined by valid_until. \n\nIf the revoked property is 'true' then this property MUST be ignored." + }, + "valid_until": { + "$ref": "data-types/timestamp.json", + "description": "The time at which this playbook should no longer be considered a valid playbook to be executed. \n\nIf the valid_until property is omitted, then there is no constraint on the latest time for which the playbook is valid. \n\nThis property MUST be greater than the timestamp in the valid_from property if the valid_from property is defined. \n\nIf the revoked property is true then this property MUST be ignored." + }, + "derived_from": { + "type": "array", + "description": "The ID of one or more CACAO playbooks that this playbook was derived from. The ID MUST represent a CACAO playbook object.", + "items": { + "$ref": "data-types/identifier.json" + }, + "minItems": 1 + }, + "related_to": { + "type": "array", + "description": "The ID of one or more related STIX or CACAO objects that this playbook is related to. \n\nThe ID SHOULD represent a CACAO playbook object, but MAY represent any STIX v2.1 CTI object or a TC approved extension.", + "items": { + "$ref": "data-types/identifier.json" + }, + "minItems": 1 + }, + "priority": { + "type": "integer", + "minimum": 0, + "maximum": 100, + "description": "A number (𝕎 - whole number) that represents the priority of this playbook relative to other defined playbooks. \n\nPriority in the context of CACAO is a subjective assessment; thus, producers of playbooks, sharing organizations, and marketplaces MAY define rules on how priority should be assessed and assigned. This specification does not address how this assessment is determined. This property is primarily to allow such usage without requiring the addition of a custom property for such practices. \n\nIf specified, the value of this property MUST be between 0 and 100. \n\nWhen left blank this means unspecified. A value of 0 means specifically undefined. Values range from 1, the highest priority, to a value of 100, the lowest. \n\nThe values of 1-100 in this property are inverted from severity and impact based on how the concept of priority is used today. For example, in a SOC a P1 ticket is a higher priority than a P4 ticket." + }, + "severity": { + "type": "integer", + "minimum": 0, + "maximum": 100, + "description": "A number (𝕎 - whole number) that represents the seriousness of the conditions that this playbook addresses. This is highly dependent on whether the playbook is a response to an incident (in which case the severity could be mapped to an incident category defined in some solution), a response to a threat (in which case the severity would likely be mapped to the severity of the threat faced or captured by threat intelligence), or a response to something else. \n\nMarketplaces and sharing organizations MAY define additional rules for how this property should be assigned. This specification does not address how this assessment is determined. \n\nIf specified, the value of this property MUST be between 0 and 100. \n\nWhen left blank this means unspecified. A value of 0 means specifically undefined. Values range from 1, the lowest severity, to a value of 100, the highest." + }, + "impact": { + "type": "integer", + "minimum": 0, + "maximum": 100, + "description": "A number (𝕎 - whole number) from 0 to 100 that represents the potential impact (as determined subjectively by the producer) the execution of the playbook might have on the organization and its infrastructure. \n\nIf specified, the value of this property MUST be between 0 and 100. When left blank this means unspecified. A value of 0 means specifically undefined or benign. Impact values range from 1, the lowest impact, to a value of 100, the highest. \n\nMarketplaces and sharing organizations MAY define additional rules for how this property should be assigned. This specification does not address how this assessment is determined. \n\nNOTE: The value of this property is not related to what triggered the playbook in the first place, such as a threat or an incident. \n\nExecuting a playbook with a higher impact score may increase the likelihood of an effect on the organization. For example, a purely investigative playbook that is non-invasive could have a low impact value of 1. In contrast, a playbook that performs firewall changes, IPS changes, moves laptops to a quarantine VLAN etc., would have a higher impact value." + }, + "industry_sectors": { + "type": "array", + "description": "A list of industry sectors that this playbook may be related or applicable to. \n\nAny industry sectors that are used in other parts of this playbook MUST also be included in this property. Any industry sectors that are used in other referenced playbooks MAY also be included in this property. \n\nThe values for this property SHOULD come from the 'industry-sector-ov' vocabulary.", + "items": { + "$ref": "#/$defs/industry-sector-ov" + }, + "minItems": 1 + }, + "labels": { + "type": "array", + "description": "A set of terms, labels, or tags associated with this playbook. The values may be user, organization, or trust-group defined and their meaning is outside the scope of this specification.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "external_references": { + "type": "array", + "description": "A list of external references for this playbook or content found in this playbook. \n\nAny external references that are used in other parts of this playbook MUST also be included in this property. Any external references that are used in other referenced playbooks MAY also be included in this property.", + "items": { + "$ref": "data-types/external-reference.json" + }, + "minItems": 1 + }, + "markings": { + "type": "array", + "description": "A list of data marking objects that apply to this playbook. In some cases, though uncommon, data markings themselves may be marked with sharing or handling guidance. In this case, this property MUST NOT contain any references to the same data marking object (i.e., it cannot contain any circular references). \n\nEach ID MUST represent a CACAO data marking object.", + "items": { + "$ref": "data-types/identifier.json" + }, + "minItems": 1 + }, + "playbook_variables": { + "type": "object", + "description": "This property contains the global variables (see section 10.18.1 for information about variable scope) that can be used within the playbook, workflow steps (including conditional steps), commands, agents, and targets defined within the playbook. See section 10.18 for information about referencing variables. \n\nThe key for each entry in the dictionary MUST be a 'string' that uniquely identifies the variable. The value for each key MUST be a CACAO 'variable' data type (see section 10.18).", + "patternProperties": { + "^__[a-zA-Z_][a-zA-Z0-9_-]{0,199}__$": { + "$ref": "data-types/variable.json" + } + } + }, + "workflow_start": { + "$ref": "data-types/identifier.json", + "description": "The first workflow step included in the workflow property that MUST be executed when starting the workflow. \n\nThe ID MUST represent a CACAO workflow start step object and that object MUST be included in the workflow property. This property is an implementation helper so that the entire workflow does not need to be parsed to find the start step." + }, + "workflow_exception": { + "$ref": "data-types/identifier.json", + "description": "The workflow step invoked whenever a playbook execution exception condition occurs. \n\nIf defined, the ID MUST represent a CACAO workflow step object and that object MUST be included in the workflow property." + }, + "workflow": { + "description": "The workflow property contains the processing logic for the playbook as workflow steps. All playbooks MUST contain at least the following three steps: a start step, an action/playbook-action step, and an end step. \n\nThe key for each entry in the dictionary MUST be an 'identifier' that uniquely identifies the workflow step (see section 10.10 for more information on identifiers). The value for each key MUST be a CACAO workflow step object (see section 4).", + "type": "object", + "patternProperties": { + "^action--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "workflows/action.json" + }, + "^end--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "workflows/end.json" + }, + "^if-condition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "workflows/if-condition.json" + }, + "^parallel--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "workflows/parallel.json" + }, + "^playbook-action--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "workflows/playbook-action.json" + }, + "^start--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "workflows/start.json" + }, + "^switch-condition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "workflows/switch-condition.json" + }, + "^while-condition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "workflows/while-condition.json" + } + } + }, + "playbook_extensions": { + "minProperties": 1, + "type": "object", + "patternProperties": { + "^extension-definition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "type": "object" + } + }, + "description": "This property declares the extensions that are in use on this playbook (at the metadata level, see section 3.1) and contains the properties and values that are to be used by the extensions. \n\nThe key for each entry in the dictionary MUST be an 'identifier' (see section 10.10 for more information on identifiers) that uniquely identifies the extension. The value for each key is a JSON object that contains the structure as defined in the extension definition's schema property. The actual property extension definition is located in the extension_definitions property." + }, + "authentication_info_definitions": { + "minProperties": 1, + "type": "object", + "patternProperties": { + "^http-basic--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "authentication-info/http-basic.json" + }, + "^oauth2--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "authentication-info/oauth2.json" + }, + "^user-auth--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "authentication-info/user-auth.json" + }, + "^[a-z]([-a-z]*[a-z])?--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "authentication-info/authentication-info.json" + } + }, + "description": "A dictionary of authentication information that can be referenced from agents and targets in workflow steps found in the workflow property. \n\nThe authentication information can be used by agents and targets when performing interactions that require authentication. \n\nThe key for each entry in the dictionary MUST be an 'identifier' that uniquely identifies the authentication information (see section 10.10 for more information on identifiers). The value for each key MUST be a CACAO 'authentication-info' object (see section 6). \n\nAny authentication information that is used in other parts of this playbook MUST also be included in this property." + }, + "agent_definitions": { + "minProperties": 1, + "type": "object", + "patternProperties": { + "^group--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/group.json" + }, + "^http-api--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/http-api.json" + }, + "^individual--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/individual.json" + }, + "^linux--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/linux.json" + }, + "^location--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/location.json" + }, + "^net-address--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/net-address.json" + }, + "^organization--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/organization.json" + }, + "^sector--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/sector.json" + }, + "^security-category--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/security-category.json" + }, + "^ssh--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/ssh.json" + }, + "^[a-z]([-a-z]*[a-z])?--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/agent-target.json" + } + }, + "description": "A dictionary of agents that can be referenced from workflow steps found in the workflow property. \n\nThe key for each entry in the dictionary MUST be an 'identifier' that uniquely identifies the agent (see section 10.10 for more information on identifiers). The value for each key MUST be a CACAO 'agent-target' object (see section 7). \n\nAny agents that are used in other parts of this playbook MUST also be included in this property." + }, + "target_definitions": { + "minProperties": 1, + "type": "object", + "patternProperties": { + "^group--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/group.json" + }, + "^http-api--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/http-api.json" + }, + "^individual--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/individual.json" + }, + "^linux--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/linux.json" + }, + "^location--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/location.json" + }, + "^net-address--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/net-address.json" + }, + "^organization--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/organization.json" + }, + "^sector--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/sector.json" + }, + "^security-category--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/security-category.json" + }, + "^ssh--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/ssh.json" + }, + "^[a-z]([-a-z]*[a-z])?--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "agent-target/agent-target.json" + } + }, + "description": "A dictionary of targets that can be referenced from workflow steps found in the workflow property. \n\nThe key for each entry in the dictionary MUST be an 'identifier' that uniquely identifies the target (see section 10.10 for more information on identifiers). The value for each key MUST be a CACAO 'agent-target' object (see section 7). \n\nAny targets that are used in other parts of this playbook MUST also be included in this property." + }, + "extension_definitions": { + "type": "object", + "patternProperties": { + "^extension-definition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "extension-definition/extension-definition.json" + } + }, + "description": "A dictionary of extension definitions that are referenced from workflow steps found in the workflow property. \n\nThe key for each entry in the dictionary MUST be an 'identifier' that uniquely identifies the extension (see section 10.10 for more information on identifiers). The value for each key MUST be a CACAO extension object (see section 7). \n\nAny extensions that are used in other parts of this playbook MUST also be included in this property." + }, + "data_marking_definitions": { + "type": "object", + "description": "A dictionary of data marking definitions that can be referenced from the playbook found in the markings property. \n\nThe key for each entry in the dictionary MUST be an 'identifier' that uniquely identifies the data marking (see section 10.10 for more information on identifiers). The value for each key MUST be a CACAO data marking object (see section 9). \n\nAny data markings that are used in other parts of this playbook MUST also be included in this property.", + "patternProperties": { + "^marking-tlp--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "data-markings/marking-tlp.json" + }, + "^marking-iep--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "data-markings/marking-iep.json" + }, + "^marking-statement--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "$ref": "data-markings/marking-statement.json" + } + } + }, + "signatures": { + "type": "array", + "description": "A list of digital signatures for this playbook. Adding a signature to a playbook does not represent a version change of the playbook. See sections 2.5, 10.15, and Appendix A for more information and a detailed example.", + "items": { + "$ref": "data-types/signature.json" + }, + "minItems": 1 + } + }, + "required": [ + "type", + "spec_version", + "id", + "name", + "created_by", + "created", + "modified", + "workflow_start", + "workflow" + ], + "$defs": { + "playbook-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "attack", + "detection", + "engagement", + "investigation", + "mitigation", + "notification", + "prevention", + "remediation" + ] + } + ] + }, + "playbook-activity-type-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "compose-content", + "deliver-content", + "identify-audience", + "identify-channel", + "scan-system", + "match-indicator", + "analyze-collected-data", + "identify-indicators", + "scan-vulnerabilities", + "configure-systems", + "restrict-access", + "disconnect-system", + "eliminate-risk", + "revert-system", + "restore-data", + "restore-capabilities", + "map-network", + "identify-steps", + "step-sequence", + "prepare-engagement", + "execute-operation", + "analyze-engagement-results" + ] + } + ] + }, + "industry-sector-ov": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "enum": [ + "aerospace", + "aviation", + "agriculture", + "automotive", + "biotechnology", + "chemical", + "commercial", + "consulting", + "construction", + "cosmetics", + "critical-infrastructure", + "dams", + "defense", + "education", + "emergency-services", + "energy", + "non-renewable-energy", + "renewable-energy", + "media", + "financial", + "food", + "gambling", + "government", + "local-government", + "national-government", + "regional-government", + "public-services", + "healthcare", + "information-communications-technology", + "electronics-hardware", + "software", + "telecommunications", + "legal-services", + "lodging", + "manufacturing", + "maritime", + "metals", + "mining", + "non-profit", + "humanitarian-aid", + "human-rights", + "nuclear", + "petroleum", + "pharmaceuticals", + "research", + "transportation", + "logistics-shipping", + "utilities", + "video-game", + "water" + ] + } + ] + } + } +} \ No newline at end of file diff --git a/models/validator/schemas/workflows/action.json b/models/validator/schemas/workflows/action.json new file mode 100644 index 00000000..89038050 --- /dev/null +++ b/models/validator/schemas/workflows/action.json @@ -0,0 +1,62 @@ +{ + "$id": "workflows", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "action", + "description": "The action step workflow step contains the actual commands to be executed by an agent against a set of targets. These commands are intended to be processed sequentially. In addition to the inherited properties, this section defines five more specific properties that are valid for this type.", + "allOf": [ + { + "$ref": "workflow-step.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'action'.", + "enum": [ + "action" + ] + }, + "commands": { + "type": "array", + "description": "A list of commands that are to be executed as part of this step. If more than one command is listed, the commands MUST be processed in the order in which they are listed (see section 5). All commands in a given step MUST be applicable to all the agents and all the targets defined in that step.", + "items": { + "$ref": "../commands/command-data.json" + }, + "minItems": 1 + }, + "agent": { + "$ref": "../data-types/identifier.json", + "description": "This property contains an ID reference to a CACAO 'agent-target' object that is stored at the playbook level in the 'agent_definitions' property. This agent MUST execute the commands defined in this step. As stated in section 7, agents are the entities that execute commands on or against targets. \n\nThe ID MUST reference a CACAO agent-target object (see section 7)." + }, + "targets": { + "type": "array", + "description": "This property contains a list of ID references to CACAO 'agent-target' objects that are stored at the playbook level in the target_definitions property. \n\nEach ID MUST reference a CACAO 'agent-target' object (see section 7). If defined, this list MUST have at least one identifier.", + "items": { + "$ref": "../data-types/identifier.json" + }, + "minItems": 1 + }, + "in_args": { + "type": "array", + "description": "The list of variable names from the local 'step_variables' dictionary (see section 4.1) or passed into this step from the global 'playbook_variables' dictionary (see section 3.1) that are used in either an agent or one of the target(s) associated with this step. See section 10.18 for more information about variables.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "out_args": { + "type": "array", + "description": "The list of variable names from the local 'step_variables' dictionary (see section 4.1) or global 'playbook_variables' dictionary (see section 3.1) that are to be returned to this step after execution of the commands by the agent(s). Implementations SHOULD strongly discourage the use of overloading of variable names, meaning using the same variable name at the step level that is also in use at the playbook level. This is to avoid issues with implementations. However, if the variable name is reused at the step level, then only that instance of the variable SHOULD be updated. See section 10.18 for more information about variables.", + "items": { + "type": "string" + }, + "minItems": 1 + } + } + } + ], + "required": [ + "commands", + "agent" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/workflows/end.json b/models/validator/schemas/workflows/end.json new file mode 100644 index 00000000..33e127d9 --- /dev/null +++ b/models/validator/schemas/workflows/end.json @@ -0,0 +1,44 @@ +{ + "$id": "workflows", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "end", + "description": "The end step workflow step is the ending point of a playbook or branch of step (e.g., a list of steps that are part of a parallel processing branch) and represents an explicit point in the workflow to signify the end of a playbook or branch of steps. While this type inherits all of the common properties of a workflow step it does not define any additional properties. When a playbook or branch of a playbook terminates it MUST call an end step. This workflow step MUST NOT use the 'on_completion', 'on_success', or 'on_failure' properties. While an end step MUST exist for the overall workflow, additional end steps MAY be present for workflow branches.", + "type": "object", + "allOf": [ + { + "$ref": "workflow-step.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'end'.", + "enum": [ + "end" + ] + } + } + }, + { + "not": { + "anyOf": [ + { + "required": [ + "on_completion" + ] + }, + { + "required": [ + "on_failure" + ] + }, + { + "required": [ + "on_success" + ] + } + ] + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/workflows/if-condition.json b/models/validator/schemas/workflows/if-condition.json new file mode 100644 index 00000000..5ff48c79 --- /dev/null +++ b/models/validator/schemas/workflows/if-condition.json @@ -0,0 +1,41 @@ +{ + "$id": "workflows", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "if-condition", + "description": "The if condition step workflow step defines the 'if-then-else' conditional logic that can be used within the workflow of the playbook. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "workflow-step.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'if-condition'.", + "enum": [ + "if-condition" + ] + }, + "condition": { + "type": "string", + "description": "A boolean expression as defined in the STIX Patterning Grammar that when it evaluates as true executes the workflow step identified by the 'on_true' property, otherwise it executes the 'on_false' workflow step." + }, + "on_true": { + "type": "string", + "description": "The step ID to be processed if the condition evaluates as true. \n\nThe entry in the 'on_true' property forms a branch of steps that are to be executed, even if there is only one workflow step in the branch. This branch MUST reference a unique end step when that branch has completed processing. This allows implementations to know when to return to the original if condition step that started that branch to look for any 'on_completion', 'on_success', or 'on_failure' actions. \n\nThe ID MUST represent a CACAO workflow step object.", + "$ref": "../data-types/identifier.json" + }, + "on_false": { + "type": "string", + "description": "The step ID to be processed if the condition evaluates as false. \n\nThe entry in the 'on_false' property forms a branch of steps that are to be executed, even if there is only one workflow step in the branch. This branch MUST reference a unique end step when that branch has completed processing. This allows implementations to know when to return to the original if condition step that started that branch to look for any 'on_completion', 'on_success', or 'on_failure' actions. \n\nThe ID MUST represent a CACAO workflow step object.", + "$ref": "../data-types/identifier.json" + } + } + } + ], + "required": [ + "condition", + "on_true" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/workflows/parallel.json b/models/validator/schemas/workflows/parallel.json new file mode 100644 index 00000000..faac4863 --- /dev/null +++ b/models/validator/schemas/workflows/parallel.json @@ -0,0 +1,34 @@ +{ + "$id": "workflows", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "parallel", + "description": "The parallel step workflow step defines how to create steps that are processed in parallel. This workflow step allows playbook authors to define two or more steps that can be executed at the same time. For example, a playbook that responds to an incident may require both the network team and the desktop team to investigate and respond to a threat at the same time. Another example is a response to a cyber attack on an operational technology (OT) environment that requires releasing air / steam / water pressure simultaneously. In addition to the inherited properties, this section defines the following additional property that is valid for this type. Implementations MUST wait for all steps referenced in the 'next_steps' property to complete before moving on. \n\nThe steps referenced from this object are intended to be processed in parallel, however, if an implementation cannot support executing steps in parallel, then the steps MAY be executed in sequential order if the desired outcome is the same.", + "type": "object", + "allOf": [ + { + "$ref": "workflow-step.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'parallel'.", + "enum": [ + "parallel" + ] + }, + "next_steps": { + "type": "array", + "description": "A list of two or more workflow steps to be processed in parallel. The 'next_steps' MUST contain at least two values. If there is only one value, then the parallel step MUST NOT be used. \n\nEach entry in the next_steps property forms a branch of steps that are to be executed, even if there is only one workflow step in the branch. Each branch MUST reference a unique end step when that branch has completed processing. This allows implementations to know when to return to the original parallel step that started that branch to look for any 'on_completion', 'on_success', or 'on_failure' actions. \n\nThe definition of parallel execution and how many parallel steps that are possible to execute is implementation dependent and is not part of this specification. \n\nIf any of the steps referenced in next_steps generate an error of any kind (exception or timeout) then implementers SHOULD consider defining rollback error handling for the playbook and include those steps in the playbook itself. \n\nEach ID MUST represent a CACAO workflow step object.", + "items": { + "$ref": "../data-types/identifier.json" + }, + "minItems": 2 + } + } + } + ], + "required": [ + "next_steps" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/workflows/playbook-action.json b/models/validator/schemas/workflows/playbook-action.json new file mode 100644 index 00000000..a7596cf2 --- /dev/null +++ b/models/validator/schemas/workflows/playbook-action.json @@ -0,0 +1,50 @@ +{ + "$id": "workflows", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "playbook-action", + "description": "The playbook action step workflow step executes a referenced playbook using the agents and targets defined in the referenced playbook. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "workflow-step.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'playbook-action'.", + "enum": [ + "playbook-action" + ] + }, + "playbook_id": { + "$ref": "../data-types/identifier.json", + "description": "The referenced playbook to execute. The playbook ID SHOULD be defined such that it is locally relevant to the system that will execute the playbook." + }, + "playbook_version": { + "$ref": "../data-types/timestamp.json", + "description": "The version of the CACAO playbook that this step references. \n\nThe value of this property MUST be the modified 'timestamp' from the CACAO playbook that this step references. If this property is not defined then the latest version that is known or available is considered valid." + }, + "in_args": { + "type": "array", + "description": "The list of variable names from the local 'step_variables' dictionary (see section 4.1) or passed into this step from the global 'playbook_variables' dictionary (see section 3.1) that are used in this playbook. See section 10.18 for more information about variables.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "out_args": { + "type": "array", + "description": "The list of variable names from the local step_variables dictionary (see section 4.1) or global 'playbook_variables' dictionary (see section 3.1) that are to be returned from this playbook after execution and stored in the same variable dictionary. See section 10.18 for more information about variables.", + "items": { + "type": "string" + }, + "minItems": 1 + } + } + } + ], + "required": [ + "playbook_id" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/workflows/start.json b/models/validator/schemas/workflows/start.json new file mode 100644 index 00000000..eeb52efa --- /dev/null +++ b/models/validator/schemas/workflows/start.json @@ -0,0 +1,39 @@ +{ + "$id": "workflows", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "start", + "description": "The start step workflow step is the starting point of a playbook and represents an explicit entry in the workflow to signify the start of a playbook. While this type inherits all of the common properties of a workflow step it does not define any additional properties. This workflow step MUST NOT use the 'on_success' or 'on_failure' properties.", + "type": "object", + "allOf": [ + { + "$ref": "workflow-step.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'start'.", + "enum": [ + "start" + ] + } + } + }, + { + "not": { + "anyOf": [ + { + "required": [ + "on_failure" + ] + }, + { + "required": [ + "on_success" + ] + } + ] + } + } + ] +} \ No newline at end of file diff --git a/models/validator/schemas/workflows/switch-condition.json b/models/validator/schemas/workflows/switch-condition.json new file mode 100644 index 00000000..81f2541f --- /dev/null +++ b/models/validator/schemas/workflows/switch-condition.json @@ -0,0 +1,73 @@ +{ + "$id": "workflows", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "switch-condition", + "description": "The switch condition step workflow step defines the 'switch' condition logic that can be used within the workflow of the playbook. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "workflow-step.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'switch-condition'.", + "enum": [ + "switch-condition" + ] + }, + "switch": { + "type": "string", + "description": "A variable that is evaluated to determine which key in the cases dictionary is matched against to execute the associated step." + }, + "cases": { + "description": "This property is a dictionary that defines one or more case values (as dictionary keys) and a step ID (as a key value) to be processed when the case value is matched against the switch value. \n\nThe value for each entry in the dictionary MUST be an identifier and it MUST represent a CACAO workflow step object. This value uniquely identifies the steps to be processed when that key/value is chosen (see section 10.10 for more information on identifiers). \n\nEach entry in the cases property forms a branch of steps that are to be executed, even if there is only one workflow step in the branch. Each branch MUST reference a unique end step when that branch has completed processing. This allows implementations to know when to return to the original switch condition step that started that branch to look for any on_completion, on_success, or on_failure actions. \n\nThis dictionary MAY have a 'default' case value.", + "type": "object", + "patternProperties": { + "^[a-zA-Z0-9_-]{0,250}": { + "oneOf": [ + { + "type": "string", + "pattern": "action--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + { + "type": "string", + "pattern": "end--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + { + "type": "string", + "pattern": "if-condition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + { + "type": "string", + "pattern": "parallel--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + { + "type": "string", + "pattern": "playbook--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + { + "type": "string", + "pattern": "start--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + { + "type": "string", + "pattern": "switch-condition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + { + "type": "string", + "pattern": "while-condition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + } + ] + } + } + } + } + } + ], + "required": [ + "switch", + "cases" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/workflows/while-condition.json b/models/validator/schemas/workflows/while-condition.json new file mode 100644 index 00000000..77278ead --- /dev/null +++ b/models/validator/schemas/workflows/while-condition.json @@ -0,0 +1,36 @@ +{ + "$id": "workflows", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "while-condition", + "description": "The while condition step workflow step defines the 'while' conditional logic that can be used within the workflow of the playbook. In addition to the inherited properties, this section defines the following additional properties that are valid for this type.", + "type": "object", + "allOf": [ + { + "$ref": "workflow-step.json" + }, + { + "properties": { + "type": { + "type": "string", + "description": "The value of this property MUST be 'while-condition'.", + "enum": [ + "while-condition" + ] + }, + "condition": { + "type": "string", + "description": "A boolean expression as defined in the STIX Patterning Grammar that while it is true executes the workflow step identified by 'on_true' otherwise it exits the while conditional part of the workflow step." + }, + "on_true": { + "type": "string", + "description": "The step ID to be processed every time the loop condition evaluates as true. \n\nThe entry in the on_true property forms a branch of steps that are to be executed, even if there is only one workflow step in the branch. This branch MUST reference a unique end step when that branch has completed processing. This allows implementations to know when to return to the original While Step that started that branch to look for any 'on_completion', 'on_success', or 'on_failure' actions. \n\nThe ID MUST represent a CACAO workflow step object.", + "$ref": "../data-types/identifier.json" + } + } + } + ], + "required": [ + "condition", + "on_true" + ] +} \ No newline at end of file diff --git a/models/validator/schemas/workflows/workflow-step.json b/models/validator/schemas/workflows/workflow-step.json new file mode 100644 index 00000000..746df0f1 --- /dev/null +++ b/models/validator/schemas/workflows/workflow-step.json @@ -0,0 +1,132 @@ +{ + "$id": "workflows", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "workflow-step", + "description": "Workflows contain a series of steps that are stored in a dictionary (see the workflow property in section 3.1), where the key is the step ID and the value is a workflow step. These workflow steps along with the associated commands form the building blocks for playbooks and are used to control the commands that need to be executed. Workflows steps are processed either sequentially, in parallel, or both depending on the type of steps required by the playbook. In addition to simple processing, workflow steps MAY also contain conditional and/or temporal operations to control the execution of the playbook. \n\nConditional processing means executing steps or commands after some sort of condition is met. Temporal processing means executing steps or commands either during a certain time window or after some period of time has passed. \n\nThis section defines the various workflow steps and how they may be used to define a playbook. \n\nEach workflow step contains base properties that are common across all steps. These common properties are defined in the following table. The determination of a step being successful,failing, or completing is implementation specific and is out of scope for this specification, but details MAY be included in the description property.", + "type": "object", + "properties": { + "type": { + "$ref": "#/$defs/workflow-step-type-enum", + "description": "The type of workflow step being used. The value for this property MUST come from the 'workflow-step-type-enum' enumeration." + }, + "name": { + "type": "string", + "description": "A name for this step that is meant to be displayed in a user interface or captured in a log message." + }, + "description": { + "type": "string", + "description": "More details, context, and possibly an explanation about what this step does and tries to accomplish." + }, + "external_references": { + "type": "array", + "description": "A list of external references for this step.", + "items": { + "$ref": "../data-types/external-reference.json" + }, + "minItems": 1 + }, + "delay": { + "type": "integer", + "minimum": 1, + "description": "A number (𝕎 - whole number) that represents the amount of time in milliseconds that this step SHOULD wait before it starts processing. \n\nIf specified, the value for this property MUST be greater than or equal to 0. \n\nIf this property is omitted, then the workflow step executes immediately without delay." + }, + "timeout": { + "type": "integer", + "description": "A number (𝕎 - whole number) that represents the amount of time in milliseconds that this step MUST wait before considering the step has failed. \n\nWhen a timeout has occurred for a step, the on_failure step pointer is invoked (if defined) and the information included in that call states that an ACTION_TIMEOUT occurred including the id of the step that timed out. \n\nIf specified, the value of this property MUST be greater than or equal to 0. \n\nIf this property is omitted, the system executing this workflow step SHOULD consider implementing a maximum allowed timeout to ensure that no individual workflow step can block a playbook execution indefinitely." + }, + "step_variables": { + "type": "object", + "description": "This property contains the variables that can be used within this workflow step or within commands, agents, and targets referenced by this workflow step. See section 10.18.2 for information about referencing variables. \n\nThe key for each entry in the dictionary MUST be a string that uniquely identifies the variable. The value for each key MUST be a CACAO 'variable' data type (see section 10.18.3).", + "patternProperties": { + "^__[a-zA-Z_][a-zA-Z0-9_-]{0,199}__$": { + "$ref": "../data-types/variable.json" + } + } + }, + "owner": { + "$ref": "../data-types/identifier.json", + "description": "An ID that represents the entity that is assigned as the owner or responsible party for this step. \n\nThe value of this property MUST represent a STIX 2.1+ Identity object." + }, + "on_completion": { + "$ref": "../data-types/identifier.json", + "description": "The ID of the next step to be processed upon completion of the defined commands. \n\nThe value of this property MUST represent a CACAO workflow step object. \n\nIf this property is defined, then on_success and on_failure MUST NOT be defined." + }, + "on_success": { + "$ref": "../data-types/identifier.json", + "description": "The ID of the next step to be processed if this step completes successfully. \n\nThe value of this property MUST represent a CACAO workflow step object. \n\nIf this property is defined, then on_completion MUST NOT be defined. This property MUST NOT be used on the 'start' or 'end' steps." + }, + "on_failure": { + "$ref": "../data-types/identifier.json", + "description": "The ID of the next step to be processed if this step fails to complete successfully. \n\nThe value of this property MUST represent a CACAO workflow step object. \n\nIf omitted and a failure occurs, then the playbook's exception handler found in the workflow_exception property at the Playbook level will be invoked. \n\nIf this property is defined, then on_completion MUST NOT be defined. This property MUST NOT be used on the 'start' or 'end' steps." + }, + "step_extensions": { + "minProperties": 1, + "type": "object", + "patternProperties": { + "^extension-definition--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$": { + "type": "object" + } + }, + "description": "This property declares the extensions that are in use on this step and contains any of the properties and values that are to be used by that extension. \n\nThe key for each entry in the dictionary MUST be an 'identifier' (see section 10.10 for more information on identifiers) that uniquely identifies the extension. The value for each key is a JSON object that contains the structure as defined in the extension definition's schema property. The actual step extension definition is located in the 'extension_definitions' property found at the Playbook level." + } + }, + "required": [ + "type" + ], + "anyOf": [ + { + "if": { + "properties": { + "type": { + "const": "end" + } + } + }, + "then": { + "not": { + "required": [ + "on_completion", + "on_failure", + "on_success" + ] + } + } + }, + { + "required": [ + "on_completion" + ], + "not": { + "required": [ + "on_failure", + "on_success" + ] + } + }, + { + "required": [ + "on_success" + ], + "not": { + "required": [ + "on_completion" + ] + } + } + ], + "$defs": { + "workflow-step-type-enum": { + "type": "string", + "enum": [ + "start", + "end", + "action", + "playbook-action", + "parallel", + "if-condition", + "while-condition", + "switch-condition" + ] + } + } +} \ No newline at end of file diff --git a/test/unittest/cacao/validators_test.go b/test/unittest/cacao/validators_test.go index 7a646736..dc1d3fae 100644 --- a/test/unittest/cacao/validators_test.go +++ b/test/unittest/cacao/validators_test.go @@ -28,7 +28,7 @@ func TestNotValidCacaoJsonInvalidAgentTargetType(t *testing.T) { } t.Log(errValid) - expected := "value must be \"http-api\"" + expected := "value must be 'http-api'" assert.Equal(t, strings.Contains(fmt.Sprint(errValid), expected), true) }