Configuration-driven engine that dynamically mutates incoming payloads based on conditional rules defined in YAML or JSON.
Kairo is a configuration engine that modifies payload requests into a new one. With Canaries defined in a YAML-config or JSON-config, you can specify a matching Condition that applies Mutations if the condition is met i.e - if an path with a value is found. A mutation then applies any mutation given it finds a path and mutates it to a jmes-path search condition. Refer to 'How to Run' and 'Example Usage' for further examples.
To run the engine, you need to create a Kairo() instance, load it properly with a yaml or json config - then run any condition or mutation(s) into incoming requests.
E.g -
kairo = Kairo()
kairo.load_from_yaml("canaries.yaml")
result = kairo.run({"some": "request"})
You can also create your own Condition / Mutations objects dynamically and run it through the Canary evaluator. To do so you first define a Match, and Filter objects to create your condition/mutation instances, initialize a canary object and evaluate it with an incoming payload request as such:
original_request = {"foo": {"bar": 1, "baz": 2}}
match_obj = Match(path="foo.bar", with_value=1) # create match condition
filter_obj = Filter(path="foo.bar", to_value="foo.baz") # create filter condition
condition = Condition(match=match_obj)
mutation = Mutation(filter=filter_obj)
config = {"add": "me"}
canary = Canary("test_foo_bar_baz", condition=condition, mutations=[mutation], config=config)
new_request = canary.evaluate(original_request, override=False)
new_request = {
"foo": {
"bar": 2,
"baz": 2
},
"add": "me"
}
global_config:
name: (str)
canaries:
- name: (str)
condition:
match:
path: (str)
with_value: (Any)
mutations:
- filter:
path: (str)
to_value: (str)
...
...
config:
...
{
"global_config": {
"name": (str),
"canaries": [
{
"name": (str),
"condition": {
"match": {
"path": (str),
"with_value": (Any)
}
},
"mutations": [
{
"filter": {
"path": (str),
"to_value": (str)
}
} ...
]
} ...
],
"config": (Any)
}
}
This is a dockerized python-3.12 and can be ran with Makefile commands as follows:
-
"make ps" ->
docker-compose ps -
"make build" ->
docker-compose build -
"make build-clean" ->
docker-compose build-clean -
"make exec" ->
docker-compose exec server bash -
"make up" ->
docker-compose up -
"make up-test" ->
docker-compose up test -
"make down" ->
docker-compose down
Testing can be done inside of the container. Once it's spun up you can exec into it and run tests there.
1) Make a build or new clean build.
2) Exec into the container.
3) Inside the container run commands: `python3.12 -m pytest tests`
Released under the MIT License — see LICENSE.
