1EA Rules Engine Service
2=======
3
4# TOC
5
6- [EA Rules Engine Service](#ea-rules-engine-service)
7- [TOC](#toc)
8- [Binary for EA rules engine service](#binary-for-ea-rules-engine-service)
9 - [Environment](#environment)
10- [Storage](#storage)
11 - [Database](#database)
12 - [File-based Storage (json)](#file-based-storage-json)
13 - [Environment](#environment-1)
14 - [Templates and File Parsing](#templates-and-file-parsing)
15- [Server](#server)
16 - [Endpoints](#endpoints)
17 - [Validate Command](#validate-command)
18 - [Post Commands](#post-commands)
19 - [Post Privileges](#post-privileges)
20 - [Post Default Rules](#post-default-rules)
21 - [Read Commands](#read-commands)
22 - [Read Privileges](#read-privileges)
23 - [Read Default Rules](#read-default-rules)
24 - [Read Command](#read-command)
25 - [Read Privilege](#read-privilege)
26 - [Read Default Rules for Command](#read-default-rules-for-command)
27 - [Delete command](#delete-command)
28 - [Delete Privilege](#delete-privilege)
29 - [Delete Default Rule](#delete-default-rule)
30 - [Banner](#banner)
31 - [Create Banner rules](#create-banner-rules)
32 - [Read Banner Rules](#read-banner-rules)
33 - [Read All Banner Rules](#read-all-banner-rules)
34 - [Delete Banner Rule association](#delete-banner-rule-association)
35 - [Read rules for a specific command for all banners](#read-rules-for-a-specific-command-for-all-banners)
36 - [Read rules for a specific command for a specific banner](#read-rules-for-a-specific-command-for-a-specific-banner)
37 - [Read All Rules for Command](#read-all-rules-for-command)
38
39# Binary for EA rules engine service
40
41See `config/pallets/sds/emergencyaccess/rulesengine/README.md` for how to set up service on local kind cluster.
42
43You can also run the binary manually using `just run cmd/sds/emergencyaccess/rulesengine`.
44
45### Environment
46
47During development it is possible to run the rulesengine with dev specific configuration via environment variables or command line flags.
48To configure via environment variables create a .env file in this directory with the required configuration before building the binary.
49This example .env file includes all possible environment variables, for more details on specific variables see the rest of this document.
50
51Note: This env file will only be read if the `APP_ENV` environment variable is not set when the binary starts up.
52
53```.env
54APP_ENV=local-dev
55GIN_MODE=debug
56RCLI_RES_DATA_DIR="/etc/rulesengine"
57DATABASE_CONNECTION_NAME="ret-edge-dev1-foreman:us-central1:edge-dev1"
58DATABASE_HOST="localhost"
59DATABASE_PORT="6000"
60DATABASE_NAME="edge-dev1"
61DATABASE_USERNAME="ea-rules-sa@ret-edge-dev1-foreman.iam"
62DATABASE_PASSWORD="****"
63```
64
65These variables can also be set directly via the command line:
66```bash
67just run cmd/sds/emergencyaccess/rulesengine -database-host="localhost" -database-port="6000" -database-username="myTestUser" -database-password="myTestPassword" -database-name="myTestDB"
68```
69# Storage
70
71The rulesengine currently can store rules from either a json file or a SQL DB.
72
73By default, rulesengine will start up with DB-based storage. If the `RCLI_RES_DATA_DIR` environment variable is set to a valid data directory, rulesengine will start up with file-based storage.
74
75## Database
76
77Rulesengine admin API's currently store data and read from a Postgres DB.
78It is possible to connect to a local DB instance or a GCP Cloud SQL instance.
79Connection is configured via environment variables or command line flags.
80To connect to the GCP Cloud SQL instance the instance connection name `DATABASE_CONNECTION_NAME`,
81the username of the GCP service account or user `DATABASE_USERNAME`, and database name `DATABASE_NAME` is required.
82
83To connect to a local instance the database hostname and port `DATABASE_HOST` and `DATABASE_PORT`,
84the user to connect with `DATABASE_USERNAME` and `DATABASE_PASSWORD`, as well as the `DATABASE_NAME` is required.
85
86
87
88## File-based Storage (json)
89
90### Environment
91
92Set the environment variable `RCLI_RES_DATA_DIR` to a valid root data directory.
93
94### Templates and File Parsing
95
96A template for a default ruleset:
97
98```json
99{
100 "bannerid": "default",
101 "roles": {
102 "admin": [
103 "systemctl",
104 "mkdir",
105 "rm"
106 ],
107 "dev": [
108 "kubectl",
109 "journalctl"
110 ],
111 "basic": [
112 "ls",
113 "df",
114 "du",
115 "cat",
116 "more"
117 ]
118 }
119}
120```
121
122The `default` id is special in that it will always be used at query time. To specify a ruleset for a specific banner id the following template could be used:
123
124```json
125{
126 "bannerid": "a-banner-id",
127 "roles": {
128 "a-role": [
129 "somecommand",
130 ],
131 "basic": [
132 "rm"
133 ]
134 }
135}
136```
137In the above example `rm` has been added to the basic role from the new banner id. Commands cannot be removed from roles set in default. The banner ID must be unique to a directory and the binary will throw an error at deployment if any two banner IDs are identical.
138
139# Server
140
141The rulesengine is an HTTP server.
142
143## Endpoints
144
145### Validate Command
146Returns true/false dependent on command and target. Command should only specify the directive (e.g `ls`). Full commands (e.g `ls -lah`) will always return false as the API does not parse the string in any form.
147
148__URI__: `/validatecommand`
149
150__Method__ : `POST`
151
152__Request__:
153
154```json
155{
156 "command": {
157 "name": "somecommand",
158 "type": "command"
159 },
160 "identity":
161 {
162 "earoles":["a-role"]
163 },
164 "target":
165 {
166 "bannerID":"a-banner-id"
167 }
168}
169```
170__Response__:
171
172```json
173{
174 "valid":true
175}
176```
177__Error codes__:
178code | error
179-|-
180200 | ok
181400 | bad request
182500 | internal server error
183
184
185### Post Commands
186API to update the list of existing commands in the database. Idempotent when using SQL storage.
187
188__URI__: `/admin/commands`
189
190__Method__: `POST`
191
192__Request__:
193```json
194[
195 {
196 "name":"ls"
197 },
198 {
199 "name":"ls"
200 }
201]
202```
203__Response__:
204200 OK
205
206__Error Codes__:
207code | error
208-|-
209200 | ok
210400 | bad request
211409 | conflict
212500 | internal server error
213
214### Post Privileges
215API to update the list of existing privileges in the database. Idempotent when using SQL storage..
216
217__URI__: `/admin/privileges`
218
219__Method__: `POST`
220
221__Request__:
222```json
223[
224 {
225 "name":"basic"
226 },
227 {
228 "name":"basic"
229 }
230]
231```
232__Response__:
233200 OK
234
235__Error Codes__:
236code | error
237-|-
238200 | ok
239400 | bad request
240409 | conflict
241500 | internal server error
242
243### Post Default Rules
244Returns a list of rules for which there was an error.
245
246Enum | error
247-|-
248"" | no conflict
249NoNameFoundConflict | Name not found (command or privilege missing)
250DuplicateRuleConflict | Rule already exists
251
252__URI__: `/admin/rules/default/commands`
253
254__Method__: `POST`
255
256__Request__:
257```json
258[
259 {
260 "command":"ls",
261 "privileges":["basic"]
262 },
263 {
264 "command":"cat",
265 "privileges":["basic", "admin"]
266 }
267]
268```
269__Response__:
270An empty response is returned when the status code is 200.
271When the status code is 404 the response has the following structure with a list of errors that occurred.
272
273```json
274{
275 "errors":[
276 {
277 "privilege":"basic",
278 "type":"Unknown Privilege"
279 }
280 ]
281}
282```
283
284The `type` key indicates the type of error and should always be present, while the other keys are optional keys with additional information on the error.
285
286__Error Codes__:
287code | error
288-|-
289200 | ok
290400 | bad request
291404 | not found
292500 | internal server error
293
294### Read Commands
295Returns a list of commands with their associated IDs.
296
297__URI__: `/admin/commands`
298
299__Method__: `GET`
300
301__Response__:
302```json
303[
304 {
305 "name":"ls",
306 "id":"8ada2297-1ad0-4439-9e6b-ae4ef5806976"
307 }
308]
309```
310__Error Codes__:
311code | error
312-|-
313200 | ok
314500 | internal server error
315
316### Read Privileges
317Returns a list of privileges with their associated IDs.
318
319__URI__: `/admin/privileges`
320
321__Method__: `GET`
322
323__Response__:
324```json
325[
326 {
327 "name":"basic",
328 "id":"cd88bec7-139a-4f8b-b78b-197832f61a65"
329 }
330]
331```
332__Error Codes__:
333code | error
334-|-
335200 | ok
336500 | internal server error
337
338### Read Default Rules
339
340Returns a list of rules (a command and privilege) with their associated IDs.
341
342__URI__: `/admin/rules/default/commands`
343
344__Method__: `GET`
345
346__Response__:
347
348```json
349[
350 {
351 "command":
352 {
353 "name":"ls",
354 "id":"8ada2297-1ad0-4439-9e6b-ae4ef5806976"
355 },
356 "privileges": [
357 {
358 "name":"basic",
359 "id":"cd88bec7-139a-4f8b-b78b-197832f61a65"
360 },
361 {
362 "name":"privilege",
363 "id":"cd88bec7-139a-4f8b-b78b-197832f61a66"
364 }
365 ]
366 }
367]
368```
369
370__Error Codes__:
371code | error
372-|-
373200 | ok
374500 | internal server error
375
376### Read Command
377
378Returns a specified command (`:name`) command and its associated ID.
379
380__URI__: `/admin/commands/:name`
381
382__Method__: `GET`
383
384__Response__:
385```json
386{
387 "name":"ls",
388 "id":"8ada2297-1ad0-4439-9e6b-ae4ef5806976"
389}
390```
391__Error Codes__:
392code | error
393-|-
394200 | ok
395500 | internal server error
396
397### Read Privilege
398Returns a specified privilege (`:name`) command and its associated ID.
399
400__URI__: `/admin/privileges/:name`
401
402__Method__: `GET`
403
404__Response__:
405```json
406{
407 "name":"basic",
408 "id":"cd88bec7-139a-4f8b-b78b-197832f61a65"
409}
410```
411__Error Codes__:
412code | error
413-|-
414200 | ok
415500 | internal server error
416
417### Read Default Rules for Command
418
419Returns a specified rule (`:commandName`) for a command and returns the rule (command,privilege and associated IDs).
420
421__URI__: `/admin/rules/default/commands/:commandName`
422
423__Method__: `GET`
424
425__Response__:
426
427```json
428{
429 "command":
430 {
431 "name":"ls",
432 "id":"8ada2297-1ad0-4439-9e6b-ae4ef5806976"
433 },
434 "privileges": [
435 {
436 "name":"basic",
437 "id":"cd88bec7-139a-4f8b-b78b-197832f61a65"
438 },
439 {
440 "name":"privilege",
441 "id":"cd88bec7-139a-4f8b-b78b-197832f61a66"
442 }
443 ]
444}
445```
446
447__Error Codes__:
448
449code | error
450-|-
451200 | ok
452500 | internal server error
453
454### Delete command
455Deletes a specified name from the database. Returns a conflict if the command is referred to by a rule. Returns 200 if no name was found.
456
457__URI__: `/admin/commands/:name`
458
459__Method__: `DELETE`
460
461__Response__:
462```json
463{
464 "rowsAffected":0,
465 "conflict":false
466}
467```
468__Error Codes__:
469code | error
470-|-
471200 | ok
472409 | Conflict
473500 | internal server error
474
475### Delete Privilege
476Deletes a specified name from the database. Returns a conflict if the privilege is referred to by a rule. Returns 200 if no name was found.
477
478__URI__: `/admin/privileges/:name`
479
480__Method__: `DELETE`
481
482__Response__:
483```json
484{
485 "rowsAffected":0,
486 "conflict":false
487}
488```
489__Error Codes__:
490code | error
491-|-
492200 | ok
493409 | Conflict
494500 | internal server error
495
496### Delete Default Rule
497Deletes rules associated to a specific command name. Errors returned will have different value fields corresponding to the error type. A Conflict error will have no accompanying fields.
498
499__URI__: `/admin/rules/default/commands/:commandName/privileges/:privilegeName`
500
501__Method__: `DELETE`
502
503__Response__:
504```json
505{
506 "errors" [
507 {
508 "type":"One of UnknownCommand, UnknownPrivilege, UnknownBanner, UnknownRule, or Conflict",
509 "command":"optional-command-query-value",
510 "privilege":"optional-privilege-query-value",
511 "banner":"optional-banner-query-value"
512 }
513 ],
514 "rowsAffected":0
515}
516```
517
518__Error Codes__:
519code | error
520-|-
521200 | ok
522404 | Not Found
523409 | Conflict
524500 | Internal Server Error
525
526
527### Banner
528
529The admin banner rules api's allow configuring additional rules that are specific to a
530particular banner.
531
532#### Create Banner rules
533
534Create one or more new rules that apply to a single banner.
535
536__URI__: `/admin/rules/banner/commands?bannerName=<bannerName>`
537
538__Method__: `POST`
539
540__Request__:
541
542```json
543[
544 {
545 "command": "<commandName",
546 "privileges": ["<privilegeName>"]
547 }
548]
549```
550
551__Response__:
552
553Returns an empty response body when the rules are accepted and saved to the Database.
554Returns a list of errors with an error `type` when one or more of the rules are referencing an unknown name.
555Error `type` will be one of `Unknown Command`, `Unknown Privilege`, or `Unknown Banner`.
556The other keys will only be present when the error type corresponds to the key name.
557
558```json
559{
560 "errors": [
561 {
562 "banner": "<bannerName>",
563 "privilege": "<privilegeName>",
564 "command": "<commandName>",
565 "type": "<type>"
566 },
567 ]
568}
569```
570
571__Error Codes__:
572
573code | error | reason
574-| - | -
575200 | ok | New rules saved with no error
576400 | bad request | Request is invalid and no rules saved
577404 | not found | Request is invalid due to unknown names, and no rules are saved
578500 | internal server error | Unexpected server error
579
580
581#### Read Banner Rules
582
583Read all rules that only apply to a specific banner
584
585__URI__: `/admin/rules/banner/commands?bannerName=<bannerName>`
586
587__Method__: `GET`
588
589__Response__:
590
591```json
592[
593 {
594 "command": {
595 "name": "<commandName>",
596 "id": "<commandID>",
597 },
598 "privileges": [
599 {
600 "name": "<privilegeName>",
601 "id": "<privilegeID>",
602 }
603 ]
604 }
605]
606```
607
608__Error Codes__:
609code | error
610-|-
611200 | ok
612500 | internal server error
613
614#### Read All Banner Rules
615
616Returns a list of rules showing all banners which have additional banner specific rules, and the privileges associated with the rule
617
618__URI__: `/admin/rules/banner/commands`
619
620__Method__: `GET`
621
622__Response__:
623
624```json
625[
626 {
627 "command": {
628 "name": "<commandName>",
629 "id": "<commandID>",
630 },
631 "banners": [
632 {
633 "banner": {
634 "id": "<bannerID>",
635 "name": "<bannerName>"
636 },
637 "privileges": [
638 {
639 "id": "<privilegeID>",
640 "name": "<privilegeName>"
641 }
642 ]
643 },
644 ]
645 }
646]
647```
648
649__Error Codes__:
650code | error
651-|-
652200 | ok
653500 | internal server error
654
655#### Delete Banner Rule association
656
657Remove a specific privilege from a banner specific rule.
658
659__URI__: `/admin/rules/banner/commands/<commandName>/privileges/<privilegeName>?bannerName=<bannerName>`
660
661__Method__: `DELETE`
662
663__Response__:
664
665Returns a JSON object with the number of rule associations deleted, and an optional `errors` list returned when the request fails with details.
666
667```json
668{
669 "errors": [
670 {
671 "type": "string: Type of error (see below)",
672 "command": "string(optional): <commandName>",
673 "privilege": "string(optional): <privilegeName>",
674 "banner": "string(optional): <bannerName>"
675 }
676 ]
677}
678```
679
680Where the error `type` is one of the following:
681- `Unknown Banner`: The specified banner with name `<bannerName>` cannot be found in the database
682- `Unknown Command`: The specified command with name `<commandName>` cannot be found in the database
683- `Unknown Privilege`: The specified privileg with name `<privilegeName>` cannot be found in the database
684- `Unknown Rule association`: The given privilege does not currently exist for the specified command and banner
685
686__Error Codes__:
687
688code | error
689-|-
690200 | ok
691404 | Not Found
692500 | Internal Server Error
693
694#### Read rules for a specific command for all banners
695
696Returns a rule showing all banners which have additional banner specific rules,
697and the privileges associated with the rule
698for a rule associated with a specific command
699
700__URI__: `/admin/rules/banner/commands/<commandName>`
701
702__Method__: `GET`
703
704__Response__:
705
706```json
707{
708 "command": {
709 "name": "<commandName>",
710 "id": "<commandID>",
711 },
712 "banners": [
713 {
714 "banner": {
715 "id": "<bannerID>",
716 "name": "<bannerName>"
717 },
718 "privileges": [
719 {
720 "id": "<privilegeID>",
721 "name": "<privilegeName>"
722 }
723 ]
724 }
725 ]
726}
727```
728
729__Error Codes__:
730code | error
731-|-
732200 | ok
733500 | internal server error
734
735
736#### Read rules for a specific command for a specific banner
737
738Read all rules that only apply to a specific banner and command
739
740__URI__: `/admin/rules/banner/commands/<commandName>?bannerName=<bannerName>`
741
742__Method__: `GET`
743
744__Response__:
745
746```json
747 {
748 "command": {
749 "name": "<commandName>",
750 "id": "<commandID>",
751 },
752 "privileges": [
753 {
754 "name": "<privilegeName>",
755 "id": "<privilegeID>",
756 }
757 ]
758 }
759```
760
761__Error Codes__:
762code | error
763-|-
764200 | ok
765500 | internal server error
766
767#### Read All Rules for Command
768Read rules relating to a command, including default and banner specific overrides.
769
770__URI__: `/admin/rules/commands/<commandName>`
771
772__Method__: `GET`
773
774__Response__:
775Returns a json object with the command, command ID, default privileges and banner specific privileges for that command.
776
777```json
778
779{
780 "command": {
781 "id": "<id>",
782 "name": "<name>"
783 },
784 "default": {
785 "privileges": [
786 {
787 "id": "<id>",
788 "name": "<name>"
789 }
790 ]
791 },
792 "banners": [
793 {
794 "banner": {
795 "id": "<id>",
796 "name": "<name>"
797 },
798 "privileges": [
799 {
800 "id": "<id>",
801 "name": "<name>"
802 }
803 ]
804 }
805 ]
806}
807
808```
809If no command is listed in the database or if there is a commmand but no rules are listed for that command, the json `null` response will be returned. If there are no rules associated to it (default or banner specific), the empty datatypes will be returned for `banners` (`[]`) or `default` (`{}`).
810
811
812__Error Codes__:
813
814code | error
815-|-
816200 | ok
817500 | Internal Server Error
View as plain text