1 package rulestest
2
3 import (
4 "bytes"
5 "fmt"
6 "net/http"
7 "strings"
8 "testing"
9
10 "github.com/gin-gonic/gin"
11 "github.com/stretchr/testify/require"
12
13 "edge-infra.dev/pkg/lib/fog"
14 rulesengine "edge-infra.dev/pkg/sds/emergencyaccess/rules"
15 "edge-infra.dev/pkg/sds/emergencyaccess/rules/server"
16 "edge-infra.dev/pkg/sds/emergencyaccess/rules/storage/file"
17 "edge-infra.dev/test/f2"
18 "edge-infra.dev/test/f2/x/postgres"
19 )
20
21 func setupRulesEngineNoDB(t *testing.T, dir string) (*gin.Engine, *bytes.Buffer) {
22 gin.SetMode(gin.TestMode)
23 router := gin.New()
24 buf := new(bytes.Buffer)
25 log := fog.New(fog.To(buf))
26
27 ds, err := file.New(log, dir)
28 require.NoError(t, err)
29
30 re := rulesengine.New(ds)
31 res, err := server.New(router, re, log)
32 require.NoError(t, err)
33
34 return res.GinEngine, buf
35 }
36
37 func TestValidateNoDB(t *testing.T) {
38 var (
39 testJSONDataDir = createTestDataDir(t, testdata)
40 reng *gin.Engine
41 )
42
43 feat := f2.NewFeature("Validate no DB").
44 Setup("Setup Rules Engine No DB", func(ctx f2.Context, t *testing.T) f2.Context {
45 reng, _ = setupRulesEngineNoDB(t, testJSONDataDir)
46 return ctx
47 }).
48 Test("Test Validate Command Default Rule", validateDefaultRuleCommand(&reng)).
49 Test("Test Validate Command Banner Rule", validateBannerRuleCommand(&reng)).
50 Test("Test Validate Command Wrong role", validateCommandWrongRole(&reng)).
51 Test("Test Validate Command Not Listed", validateCommandNotListed(&reng)).
52 Test("Test Validate Command Wrong Banner", validateCommandWrongBanner(&reng)).
53 Feature()
54 f.Test(t, feat)
55 }
56
57 func TestValidateWithDB(t *testing.T) {
58 var (
59 reng *gin.Engine
60 buf *bytes.Buffer
61 )
62
63 feat := f2.NewFeature("Validation with DB").
64 Setup("Create Rules Engine server", func(ctx f2.Context, t *testing.T) f2.Context {
65 var db = postgres.FromContextT(ctx, t).DB()
66 reng, buf = setupRulesEngine(t, db)
67 return ctx
68 }).
69 Setup("Add some data", func(ctx f2.Context, t *testing.T) f2.Context {
70 var (
71 db = postgres.FromContextT(ctx, t).DB()
72 )
73 _, err := db.ExecContext(ctx, validationData)
74 require.NoError(t, err)
75 return ctx
76 }).
77 Test("Test Validate Command Default Rule", validateDefaultRuleCommand(&reng)).
78 Test("Test Validate Command Banner Rule", validateBannerRuleCommand(&reng)).
79 Test("Test Validate Command Wrong role", validateCommandWrongRole(&reng)).
80 Test("Test Validate Command Not Listed", validateCommandNotListed(&reng)).
81 Test("Test Validate Command Wrong Banner", validateCommandWrongBanner(&reng)).
82 Test("Test Validate Command No Rule", validateCommandNoRuleDB(&reng)).
83 Test("Test Validate Executable Default Rule", validateDefaultRuleExecutable(&reng)).
84 Test("Test Validate Unknown Request Type", validateUnknownCommandType(&reng)).
85 Feature()
86 f.Test(t, feat)
87 fmt.Println(buf)
88 }
89
90 const validationData = `
91 INSERT INTO ea_rules_commands (command_id, name, type)
92 VALUES
93 ('78587bb1-6ca2-4d2d-a223-1ee642514b97', 'ls', 'command'),
94 ('c818a4cd-225d-4f60-9382-f96348da7af0', 'myScript', 'executable'),
95 ('35cc70eb-689d-49d4-8bd8-fa1cb8b0928f','mv', 'command')
96 ;
97
98 INSERT INTO banners (banner_edge_id, banner_name)
99 VALUES
100 ('2f9f5965-ed2a-4262-9fd9-9d2d8f8bee8a', 'myBanner')
101 ;
102
103 INSERT INTO ea_rules_privileges (privilege_id, name)
104 VALUES
105 ('a7c379ea-6e34-4017-8e86-eb545d7856a3', 'ea-read'),
106 ('caedabee-ea7a-4421-a608-ec04106e61da', 'ea-write')
107 ;
108
109 INSERT INTO ea_rules_default (command_id, privilege_id)
110 VALUES
111 ('78587bb1-6ca2-4d2d-a223-1ee642514b97', 'a7c379ea-6e34-4017-8e86-eb545d7856a3'),
112 ('c818a4cd-225d-4f60-9382-f96348da7af0', 'a7c379ea-6e34-4017-8e86-eb545d7856a3')
113 ;
114
115 INSERT INTO ea_rules (banner_edge_id, command_id, privilege_id)
116 VALUES
117 ('2f9f5965-ed2a-4262-9fd9-9d2d8f8bee8a', '78587bb1-6ca2-4d2d-a223-1ee642514b97', 'caedabee-ea7a-4421-a608-ec04106e61da')
118 ;
119 `
120
121 func validateDefaultRuleCommand(reng **gin.Engine) func(ctx f2.Context, t *testing.T) f2.Context {
122 return func(ctx f2.Context, t *testing.T) f2.Context {
123 tc := testCase{
124 url: `/validatecommand`,
125 method: http.MethodPost,
126 body: strings.NewReader(`{
127 "command": {
128 "name": "ls",
129 "type": "command"
130 },
131 "identity":{"userid":"user@ncr.com","earoles":["ea-read"]},
132 "target":{"bannerID":"2f9f5965-ed2a-4262-9fd9-9d2d8f8bee8a"}}`),
133 expectedStatus: http.StatusOK,
134 expectedOut: `{
135 "valid":true
136 }`,
137 }
138 ctx = testEndpoint(ctx, t, *reng, tc)
139 return ctx
140 }
141 }
142 func validateBannerRuleCommand(reng **gin.Engine) func(ctx f2.Context, t *testing.T) f2.Context {
143 return func(ctx f2.Context, t *testing.T) f2.Context {
144 tc := testCase{
145 url: `/validatecommand`,
146 method: http.MethodPost,
147 body: strings.NewReader(`{
148 "command": {
149 "name": "ls",
150 "type": "command"
151 },
152 "identity":{"userid":"user@ncr.com","earoles":["ea-write"]},
153 "target":{"bannerID":"2f9f5965-ed2a-4262-9fd9-9d2d8f8bee8a"}}`),
154 expectedStatus: http.StatusOK,
155 expectedOut: `{
156 "valid":true
157 }`,
158 }
159 ctx = testEndpoint(ctx, t, *reng, tc)
160 return ctx
161 }
162 }
163 func validateCommandWrongRole(reng **gin.Engine) func(ctx f2.Context, t *testing.T) f2.Context {
164 return func(ctx f2.Context, t *testing.T) f2.Context {
165 tc := testCase{
166 url: `/validatecommand`,
167 method: http.MethodPost,
168 body: strings.NewReader(`{
169 "command": {
170 "name": "ls",
171 "type": "command"
172 },
173 "identity":{"userid":"user@ncr.com","earoles":["not-a-role"]},
174 "target":{"bannerID":"2f9f5965-ed2a-4262-9fd9-9d2d8f8bee8a"}}`),
175 expectedStatus: http.StatusOK,
176 expectedOut: `{
177 "valid":false
178 }`,
179 }
180 ctx = testEndpoint(ctx, t, *reng, tc)
181 return ctx
182 }
183 }
184 func validateCommandNotListed(reng **gin.Engine) func(ctx f2.Context, t *testing.T) f2.Context {
185 return func(ctx f2.Context, t *testing.T) f2.Context {
186 tc := testCase{
187 url: `/validatecommand`,
188 method: http.MethodPost,
189
190 body: strings.NewReader(`{
191 "command": {
192 "name": "mkdir",
193 "type": "command"
194 },
195 "identity":{"userid":"user@ncr.com","earoles":["ea-write"]},
196 "target":{"bannerID":"2f9f5965-ed2a-4262-9fd9-9d2d8f8bee8a"}}`),
197 expectedStatus: http.StatusOK,
198 expectedOut: `{
199 "valid":false
200 }`,
201 }
202 ctx = testEndpoint(ctx, t, *reng, tc)
203 return ctx
204 }
205 }
206 func validateCommandWrongBanner(reng **gin.Engine) func(ctx f2.Context, t *testing.T) f2.Context {
207 return func(ctx f2.Context, t *testing.T) f2.Context {
208 tc := testCase{
209 url: `/validatecommand`,
210 method: http.MethodPost,
211
212 body: strings.NewReader(`{
213 "command": {
214 "name": "mv",
215 "type": "command"
216 },
217 "identity":{"userid":"user@ncr.com","earoles":["ea-read"]},
218 "target":{"bannerID":"35cc70eb-689d-49d4-8bd8-fa1cb8b0928f"}}`),
219 expectedStatus: http.StatusOK,
220 expectedOut: `{
221 "valid":false
222 }`,
223 }
224 ctx = testEndpoint(ctx, t, *reng, tc)
225 return ctx
226 }
227 }
228 func validateCommandNoRuleDB(reng **gin.Engine) func(ctx f2.Context, t *testing.T) f2.Context {
229 return func(ctx f2.Context, t *testing.T) f2.Context {
230 tc := testCase{
231 url: `/validatecommand`,
232 method: http.MethodPost,
233
234 body: strings.NewReader(`{
235 "command": {
236 "name": "mv",
237 "type": "command"
238 },
239 "identity":{"userid":"user@ncr.com","earoles":["ea-read"]},
240 "target":{"bannerID":"2f9f5965-ed2a-4262-9fd9-9d2d8f8bee8a"}}`),
241 expectedStatus: http.StatusOK,
242 expectedOut: `{
243 "valid":false
244 }`,
245 }
246 ctx = testEndpoint(ctx, t, *reng, tc)
247 return ctx
248 }
249 }
250
251 func validateDefaultRuleExecutable(reng **gin.Engine) func(ctx f2.Context, t *testing.T) f2.Context {
252 return func(ctx f2.Context, t *testing.T) f2.Context {
253 tc := testCase{
254 url: `/validatecommand`,
255 method: http.MethodPost,
256 body: strings.NewReader(`
257 {
258 "command": {
259 "name": "myScript",
260 "type": "executable"
261 },
262 "identity": {
263 "userid": "user@ncr.com",
264 "earoles":["ea-read"]
265 },
266 "target": {
267 "bannerID": "2f9f5965-ed2a-4262-9fd9-9d2d8f8bee8a"
268 }
269 }
270 `),
271 expectedStatus: http.StatusOK,
272 expectedOut: `
273 {
274 "valid": true
275 }
276 `,
277 }
278 ctx = testEndpoint(ctx, t, *reng, tc)
279 return ctx
280 }
281 }
282
283 func validateUnknownCommandType(reng **gin.Engine) func(ctx f2.Context, t *testing.T) f2.Context {
284 return func(ctx f2.Context, t *testing.T) f2.Context {
285 tc := testCase{
286 url: `/validatecommand`,
287 method: http.MethodPost,
288 body: strings.NewReader(`
289 {
290 "command": {
291 "name": "myScript",
292 "type": "unknownRequestType"
293 },
294 "identity": {
295 "userid": "user@ncr.com",
296 "earoles":["ea-read"]
297 },
298 "target": {
299 "bannerID": "2f9f5965-ed2a-4262-9fd9-9d2d8f8bee8a"
300 }
301 }
302 `),
303
304
305
306
307
308
309 expectedStatus: http.StatusInternalServerError,
310 expectedOut: `null`,
311 }
312 ctx = testEndpoint(ctx, t, *reng, tc)
313 return ctx
314 }
315 }
316
View as plain text