Skip to content

Commit 08b9bab

Browse files
committed
feat: add schema for test overrides
1 parent da43d43 commit 08b9bab

File tree

8 files changed

+859
-9
lines changed

8 files changed

+859
-9
lines changed

cmd/generate-doc-yaml-schema/main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ package main
66
import (
77
"os"
88

9-
"github.com/coreruleset/ftw-tests-schema/types"
9+
"github.com/coreruleset/ftw-tests-schema/test"
1010
)
1111

1212
func main() {
13-
data, err := types.GetFTWTestDoc().Encode()
13+
data, err := test.GetFTWTestDoc().Encode()
1414
if err != nil {
1515
panic(err)
1616
}

overrides/overrides.go

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package overrides
2+
3+
import "github.com/coreruleset/ftw-tests-schema/test"
4+
5+
// Copyright 2023 Felipe Zipitria
6+
// SPDX-License-Identifier: Apache-2.0
7+
8+
//go:generate dstdocgen -package overrides -path . -structure FTWOverrides -output ./overrides_doc.go
9+
10+
var (
11+
metaExample = Meta{
12+
Engine: "libmodsecurity3",
13+
Platform: "nginx",
14+
Annotations: annotationsExample,
15+
}
16+
annotationsExample = map[string]string{
17+
"os": "Debian Bullseye",
18+
"purpose": "Bullseye integration",
19+
}
20+
reasonExample = "nginx returns 400 when `Content-Length` header is sent in a\n" +
21+
"`Transfer-Encoding: chunked` request."
22+
23+
testOverridesExample = []TestOverride{
24+
TestOverride{
25+
RuleId: 920100,
26+
TestId: 4,
27+
Reason: reasonExample,
28+
ExpectFailure: true,
29+
Output: test.ExampleOutput,
30+
},
31+
}
32+
)
33+
34+
// TODO: Welcome to the FTW YAMLFormat documentation.
35+
// In this document we will explain all the possible options that can be used within the YAML format.
36+
// Generally this is the preferred format for writing tests in as they don't require any programming skills
37+
// in order to understand and change. If you find a bug in this format please open an issue.
38+
39+
// TODO: FTWTest is the base type used when unmarshaling YAML tests files
40+
type FTWOverrides struct {
41+
// description: |
42+
// The version field designates the version of the schema that validates this file
43+
// examples:
44+
// - value: "\"v0.1.0\""
45+
Version string `yaml:"version"`
46+
47+
// description: |
48+
// Meta describes the metadata information
49+
// examples:
50+
// - value: metaExample
51+
Meta Meta `yaml:"meta"`
52+
53+
// description: |
54+
// List of test override specifications
55+
// examples:
56+
// - value: testOverridesExample
57+
TestOverrides []TestOverride `yaml:"test_overrides"`
58+
}
59+
60+
// Meta describes the metadata information of this yaml file
61+
type Meta struct {
62+
// description: |
63+
// The name of the WAF engine the tests are expected to run against
64+
// examples:
65+
// - value: "\"coraza\""
66+
Engine string `yaml:"engine"`
67+
68+
// description: |
69+
// The name of the platform (e.g., web server) the tests are expected to run against
70+
// examples:
71+
// - value: "\"nginx\""
72+
Platform string `yaml:"platform"`
73+
74+
// description: |
75+
// Custom annotations; can be used to add additional meta information
76+
// examples:
77+
// - value: annotationsExample
78+
Annotations map[string]string `yaml:"annotations"`
79+
}
80+
81+
// TestOverride describes overrides for a single test
82+
type TestOverride struct {
83+
// description: |
84+
// ID of the rule this test targets.
85+
// If this field is not empty, `test_id` must also be set.
86+
// examples:
87+
// - value: "\"920100\""
88+
RuleId int `yaml:"rule_id,omitempty"`
89+
90+
// description: |
91+
// ID of the test this override applies to.
92+
// If this field is not empty, `rule_id` must also be set.
93+
// examples:
94+
// - value: 5
95+
TestId int `yaml:"test_id,omitempty"`
96+
97+
// description: |
98+
// Regular expression matching test names (can match multiple tests).
99+
// If this field is empty, `rule_id` and `test_id` must be set.
100+
// examples:
101+
// - value: "\"^910.*$\""
102+
NameRegex string `yaml:"name_regex,omitempty"`
103+
104+
// description: |
105+
// Describes why this override is necessary.
106+
// examples:
107+
// - value: reasonExample
108+
Reason string `yaml:"reason"`
109+
110+
// description: |
111+
// Whether this test is expected to fail for this particular configuration.
112+
// Default: false
113+
// examples:
114+
// - value: true
115+
ExpectFailure bool `yaml:"expect_failure,omitempty"`
116+
117+
// description: |
118+
// Specifies overrides on the test output
119+
// examples:
120+
// - value: 400
121+
Output test.Output `yaml:"output"`
122+
}

overrides/overrides_doc.go

+194
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
// DO NOT EDIT: this file is automatically generated by docgen
5+
package overrides
6+
7+
import (
8+
"github.com/projectdiscovery/yamldoc-go/encoder"
9+
)
10+
11+
var (
12+
FTWOverridesDoc encoder.Doc
13+
MetaDoc encoder.Doc
14+
TestOverrideDoc encoder.Doc
15+
TESTOutputDoc encoder.Doc
16+
)
17+
18+
func init() {
19+
FTWOverridesDoc.Type = "FTWOverrides"
20+
FTWOverridesDoc.Comments[encoder.LineComment] = " TODO: Welcome to the FTW YAMLFormat documentation."
21+
FTWOverridesDoc.Description = "TODO: Welcome to the FTW YAMLFormat documentation.\n In this document we will explain all the possible options that can be used within the YAML format.\n Generally this is the preferred format for writing tests in as they don't require any programming skills\n in order to understand and change. If you find a bug in this format please open an issue.\n\n\n TODO: FTWTest is the base type used when unmarshaling YAML tests files"
22+
FTWOverridesDoc.Fields = make([]encoder.Doc, 3)
23+
FTWOverridesDoc.Fields[0].Name = "version"
24+
FTWOverridesDoc.Fields[0].Type = "string"
25+
FTWOverridesDoc.Fields[0].Note = ""
26+
FTWOverridesDoc.Fields[0].Description = "The version field designates the version of the schema that validates this file"
27+
FTWOverridesDoc.Fields[0].Comments[encoder.LineComment] = "The version field designates the version of the schema that validates this file"
28+
29+
FTWOverridesDoc.Fields[0].AddExample("", "v0.1.0")
30+
FTWOverridesDoc.Fields[1].Name = "meta"
31+
FTWOverridesDoc.Fields[1].Type = "Meta"
32+
FTWOverridesDoc.Fields[1].Note = ""
33+
FTWOverridesDoc.Fields[1].Description = "Meta describes the metadata information"
34+
FTWOverridesDoc.Fields[1].Comments[encoder.LineComment] = "Meta describes the metadata information"
35+
36+
FTWOverridesDoc.Fields[1].AddExample("", metaExample)
37+
FTWOverridesDoc.Fields[2].Name = "test_overrides"
38+
FTWOverridesDoc.Fields[2].Type = "[]TestOverride"
39+
FTWOverridesDoc.Fields[2].Note = ""
40+
FTWOverridesDoc.Fields[2].Description = "List of test override specifications"
41+
FTWOverridesDoc.Fields[2].Comments[encoder.LineComment] = "List of test override specifications"
42+
43+
FTWOverridesDoc.Fields[2].AddExample("", testOverridesExample)
44+
45+
MetaDoc.Type = "Meta"
46+
MetaDoc.Comments[encoder.LineComment] = ""
47+
MetaDoc.Description = ""
48+
49+
MetaDoc.AddExample("", metaExample)
50+
MetaDoc.AppearsIn = []encoder.Appearance{
51+
{
52+
TypeName: "FTWOverrides",
53+
FieldName: "meta",
54+
},
55+
}
56+
MetaDoc.Fields = make([]encoder.Doc, 3)
57+
MetaDoc.Fields[0].Name = "engine"
58+
MetaDoc.Fields[0].Type = "string"
59+
MetaDoc.Fields[0].Note = ""
60+
MetaDoc.Fields[0].Description = "The name of the WAF engine the tests are expected to run against"
61+
MetaDoc.Fields[0].Comments[encoder.LineComment] = "The name of the WAF engine the tests are expected to run against"
62+
63+
MetaDoc.Fields[0].AddExample("", "coraza")
64+
MetaDoc.Fields[1].Name = "platform"
65+
MetaDoc.Fields[1].Type = "string"
66+
MetaDoc.Fields[1].Note = ""
67+
MetaDoc.Fields[1].Description = "The name of the platform (e.g., web server) the tests are expected to run against"
68+
MetaDoc.Fields[1].Comments[encoder.LineComment] = "The name of the platform (e.g., web server) the tests are expected to run against"
69+
70+
MetaDoc.Fields[1].AddExample("", "nginx")
71+
MetaDoc.Fields[2].Name = "annotations"
72+
MetaDoc.Fields[2].Type = "map[string]string"
73+
MetaDoc.Fields[2].Note = ""
74+
MetaDoc.Fields[2].Description = "Custom annotations; can be used to add additional meta information"
75+
MetaDoc.Fields[2].Comments[encoder.LineComment] = "Custom annotations; can be used to add additional meta information"
76+
77+
MetaDoc.Fields[2].AddExample("", annotationsExample)
78+
79+
TestOverrideDoc.Type = "TestOverride"
80+
TestOverrideDoc.Comments[encoder.LineComment] = ""
81+
TestOverrideDoc.Description = ""
82+
83+
TestOverrideDoc.AddExample("", testOverridesExample)
84+
TestOverrideDoc.AppearsIn = []encoder.Appearance{
85+
{
86+
TypeName: "FTWOverrides",
87+
FieldName: "test_overrides",
88+
},
89+
}
90+
TestOverrideDoc.Fields = make([]encoder.Doc, 6)
91+
TestOverrideDoc.Fields[0].Name = "rule_id"
92+
TestOverrideDoc.Fields[0].Type = "int"
93+
TestOverrideDoc.Fields[0].Note = ""
94+
TestOverrideDoc.Fields[0].Description = "ID of the rule this test targets.\nIf this field is not empty, `test_id` must also be set."
95+
TestOverrideDoc.Fields[0].Comments[encoder.LineComment] = "ID of the rule this test targets."
96+
97+
TestOverrideDoc.Fields[0].AddExample("", "920100")
98+
TestOverrideDoc.Fields[1].Name = "test_id"
99+
TestOverrideDoc.Fields[1].Type = "int"
100+
TestOverrideDoc.Fields[1].Note = ""
101+
TestOverrideDoc.Fields[1].Description = "ID of the test this override applies to.\nIf this field is not empty, `rule_id` must also be set."
102+
TestOverrideDoc.Fields[1].Comments[encoder.LineComment] = "ID of the test this override applies to."
103+
104+
TestOverrideDoc.Fields[1].AddExample("", 5)
105+
TestOverrideDoc.Fields[2].Name = "name_regex"
106+
TestOverrideDoc.Fields[2].Type = "string"
107+
TestOverrideDoc.Fields[2].Note = ""
108+
TestOverrideDoc.Fields[2].Description = "Regular expression matching test names (can match multiple tests).\nIf this field is empty, `rule_id` and `test_id` must be set."
109+
TestOverrideDoc.Fields[2].Comments[encoder.LineComment] = "Regular expression matching test names (can match multiple tests)."
110+
111+
TestOverrideDoc.Fields[2].AddExample("", "^910.*$")
112+
TestOverrideDoc.Fields[3].Name = "reason"
113+
TestOverrideDoc.Fields[3].Type = "string"
114+
TestOverrideDoc.Fields[3].Note = ""
115+
TestOverrideDoc.Fields[3].Description = "Describes why this override is necessary."
116+
TestOverrideDoc.Fields[3].Comments[encoder.LineComment] = "Describes why this override is necessary."
117+
118+
TestOverrideDoc.Fields[3].AddExample("", reasonExample)
119+
TestOverrideDoc.Fields[4].Name = "expect_failure"
120+
TestOverrideDoc.Fields[4].Type = "bool"
121+
TestOverrideDoc.Fields[4].Note = ""
122+
TestOverrideDoc.Fields[4].Description = "Whether this test is expected to fail for this particular configuration.\nDefault: false"
123+
TestOverrideDoc.Fields[4].Comments[encoder.LineComment] = "Whether this test is expected to fail for this particular configuration."
124+
125+
TestOverrideDoc.Fields[4].AddExample("", true)
126+
TestOverrideDoc.Fields[5].Name = "output"
127+
TestOverrideDoc.Fields[5].Type = "test.Output"
128+
TestOverrideDoc.Fields[5].Note = ""
129+
TestOverrideDoc.Fields[5].Description = "Specifies overrides on the test output"
130+
TestOverrideDoc.Fields[5].Comments[encoder.LineComment] = "Specifies overrides on the test output"
131+
132+
TestOverrideDoc.Fields[5].AddExample("", 400)
133+
134+
TESTOutputDoc.Type = "test.Output"
135+
TESTOutputDoc.Comments[encoder.LineComment] = " Output is the response expected from the test"
136+
TESTOutputDoc.Description = "Output is the response expected from the test"
137+
138+
TESTOutputDoc.AddExample("", 400)
139+
TESTOutputDoc.AppearsIn = []encoder.Appearance{
140+
{
141+
TypeName: "TestOverride",
142+
FieldName: "output",
143+
},
144+
}
145+
TESTOutputDoc.Fields = make([]encoder.Doc, 5)
146+
TESTOutputDoc.Fields[0].Name = "status"
147+
TESTOutputDoc.Fields[0].Type = "[]int"
148+
TESTOutputDoc.Fields[0].Note = ""
149+
TESTOutputDoc.Fields[0].Description = "description: |\n Status describes the HTTP status error code expected as response.\n examples:\n - name: Status\n value: [200]"
150+
TESTOutputDoc.Fields[0].Comments[encoder.LineComment] = " description: |"
151+
152+
TESTOutputDoc.Fields[1].Name = "response_contains"
153+
TESTOutputDoc.Fields[1].Type = "string"
154+
TESTOutputDoc.Fields[1].Note = ""
155+
TESTOutputDoc.Fields[1].Description = "ResponseContains describes the text that should be contained in the HTTP response."
156+
TESTOutputDoc.Fields[1].Comments[encoder.LineComment] = "ResponseContains describes the text that should be contained in the HTTP response."
157+
158+
TESTOutputDoc.Fields[1].AddExample("ResponseContains", "Hello, World")
159+
TESTOutputDoc.Fields[2].Name = "log_contains"
160+
TESTOutputDoc.Fields[2].Type = "string"
161+
TESTOutputDoc.Fields[2].Note = ""
162+
TESTOutputDoc.Fields[2].Description = "LogContains describes the text that should be contained in the WAF logs."
163+
TESTOutputDoc.Fields[2].Comments[encoder.LineComment] = "LogContains describes the text that should be contained in the WAF logs."
164+
165+
TESTOutputDoc.Fields[2].AddExample("LogContains", "id 920100")
166+
TESTOutputDoc.Fields[3].Name = "no_log_contains"
167+
TESTOutputDoc.Fields[3].Type = "string"
168+
TESTOutputDoc.Fields[3].Note = ""
169+
TESTOutputDoc.Fields[3].Description = "NoLogContains describes the text that should be contained in the WAF logs."
170+
TESTOutputDoc.Fields[3].Comments[encoder.LineComment] = "NoLogContains describes the text that should be contained in the WAF logs."
171+
172+
TESTOutputDoc.Fields[3].AddExample("NoLogContains", "id 920100")
173+
TESTOutputDoc.Fields[4].Name = "expect_error"
174+
TESTOutputDoc.Fields[4].Type = "bool"
175+
TESTOutputDoc.Fields[4].Note = ""
176+
TESTOutputDoc.Fields[4].Description = "When `ExpectError` is true, we don't expect an answer from the WAF, just an error."
177+
TESTOutputDoc.Fields[4].Comments[encoder.LineComment] = "When `ExpectError` is true, we don't expect an answer from the WAF, just an error."
178+
179+
TESTOutputDoc.Fields[4].AddExample("ExpectError", false)
180+
}
181+
182+
// GetFTWOverridesDoc returns documentation for the file ./overrides_doc.go.
183+
func GetFTWOverridesDoc() *encoder.FileDoc {
184+
return &encoder.FileDoc{
185+
Name: "FTWOverrides",
186+
Description: "",
187+
Structs: []*encoder.Doc{
188+
&FTWOverridesDoc,
189+
&MetaDoc,
190+
&TestOverrideDoc,
191+
&TESTOutputDoc,
192+
},
193+
}
194+
}

0 commit comments

Comments
 (0)