...

Text file src/edge-infra.dev/cmd/sds/emergencyaccess/rulesengine/README.md

Documentation: edge-infra.dev/cmd/sds/emergencyaccess/rulesengine

     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