# encoding: utf-8
require 'json'
module Inspec
class Schema
STATISTICS = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'duration' => { 'type' => 'number' },
'controls' => {
'type' => 'object',
'optional' => true,
'properties' => {
'total' => { 'type' => 'number' },
'passed' => {
'type' => 'object',
'properties' => {
'total' => { 'type' => 'number' },
},
},
'skipped' => {
'type' => 'object',
'properties' => {
'total' => { 'type' => 'number' },
},
},
'failed' => {
'type' => 'object',
'properties' => {
'total' => { 'type' => 'number' },
},
},
},
},
},
}.freeze
PLATFORM = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'name' => { 'type' => 'string' },
'release' => { 'type' => 'string' },
},
}.freeze
# Tags are open right, with simple key-value associations and not restrictions
TAGS = { 'type' => 'object' }.freeze
RESULT = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'status' => { 'type' => 'string' },
'code_desc' => { 'type' => 'string' },
'run_time' => { 'type' => 'number' },
'start_time' => { 'type' => 'string' },
'skip_message' => { 'type' => 'string', 'optional' => true },
'resource' => { 'type' => 'string', 'optional' => true },
'message' => { 'type' => 'string', 'optional' => true },
'exception' => { 'type' => 'string', 'optional' => true },
'backtrace' => { 'type' => 'object', 'optional' => true },
},
}.freeze
REF = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'ref' => { 'type' => 'string' },
# TODO: One of these needs to be deprecated
'uri' => { 'type' => 'string', 'optional' => true },
'url' => { 'type' => 'string', 'optional' => true },
},
}.freeze
REFS = { 'type' => 'array', 'items' => REF }.freeze
CONTROL = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'id' => { 'type' => 'string' },
'title' => { 'type' => %w{string null} },
'desc' => { 'type' => %w{string null} },
'impact' => { 'type' => 'number' },
'refs' => REFS,
'tags' => TAGS,
'code' => { 'type' => 'string' },
'source_location' => {
'type' => 'object',
'properties' => {
'ref' => { 'type' => 'string' },
'line' => { 'type' => 'number' },
},
},
'results' => { 'type' => 'array', 'items' => RESULT },
},
}.freeze
SUPPORTS = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'os-family' => { 'type' => 'string', 'optional' => true },
},
}.freeze
CONTROL_GROUP = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'id' => { 'type' => 'string' },
'title' => { 'type' => 'string', 'optional' => true },
'controls' => { 'type' => 'array', 'items' => { 'type' => 'string' } },
},
}.freeze
PROFILE = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'name' => { 'type' => 'string' },
'version' => { 'type' => 'string', 'optional' => true },
'sha256' => { 'type' => 'string', 'optional' => false },
'title' => { 'type' => 'string', 'optional' => true },
'maintainer' => { 'type' => 'string', 'optional' => true },
'copyright' => { 'type' => 'string', 'optional' => true },
'copyright_email' => { 'type' => 'string', 'optional' => true },
'license' => { 'type' => 'string', 'optional' => true },
'summary' => { 'type' => 'string', 'optional' => true },
'supports' => {
'type' => 'array',
'items' => SUPPORTS,
'optional' => true,
},
'controls' => {
'type' => 'array',
'items' => CONTROL,
},
'groups' => {
'type' => 'array',
'items' => CONTROL_GROUP,
},
'attributes' => {
'type' => 'array',
# TODO: more detailed specification needed
},
},
}.freeze
EXEC_JSON = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'platform' => PLATFORM,
'profiles' => {
'type' => 'array',
'items' => PROFILE,
},
'statistics' => STATISTICS,
'version' => { 'type' => 'string' },
},
}.freeze
MIN_CONTROL = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'id' => { 'type' => 'string' },
'profile_id' => { 'type' => %w{string null} },
'profile_sha256' => { 'type' => 'string' },
'status' => { 'type' => 'string' },
'code_desc' => { 'type' => 'string' },
'skip_message' => { 'type' => 'string', 'optional' => true },
'resource' => { 'type' => 'string', 'optional' => true },
'message' => { 'type' => 'string', 'optional' => true },
'exception' => { 'type' => 'string', 'optional' => true },
'backtrace' => { 'type' => 'object', 'optional' => true },
},
}.freeze
EXEC_JSONMIN = {
'type' => 'object',
'additionalProperties' => false,
'properties' => {
'statistics' => STATISTICS,
'version' => { 'type' => 'string' },
'controls' => {
'type' => 'array',
'items' => MIN_CONTROL,
},
},
}.freeze
LIST = {
'exec-json' => EXEC_JSON,
'exec-jsonmin' => EXEC_JSONMIN,
}.freeze
def self.names
LIST.keys
end
def self.json(name)
v = LIST[name] ||
raise("Cannot find schema #{name.inspect}.")
JSON.dump(v)
end
end
end