# OPA-MongoDB Data filtering
This is cli tool to integrate OPA with mongo database.
Available commands & flags:
```
$ ./opa-mongo --help
This CLI lets you to integrate OPA with mongo DB. You can store larger contexts
that needs OPA evaluation in mongo database and defines the unknowns in rego policies
accordingly for evaluation and the unknowns are fetched from mongo with this cli
Note: Before you run this CLI make sure you have working mongo database that is accessible through this cli.
Usage:
opa_mongo [command]
Available Commands:
help Help about any command
run Run OPA with Mongo DB as server
test This command inserts static employee data for development & testing purposes.
Flags:
-c, --config.file string configuration file.
-h, --help help for opa_mongo
Use "opa-mongo [command] --help" for more information about a command.
```
You can deploy opa-mongo server in two ways:
1. Docker
2. Kubernetes
### Deploying as container:
Prerequisites:
* Docker
#### Step 1:
Running Mongo DB as container:
```
docker run -d -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=password -p 27017:27017 mongo
```
#### Step 2:
Configure the mongo db details in the config file as shown below in a file named ```config.yaml```:
```
cfg:
address: <node-ip>:27017
database: opa-mongo
username: admin
password: password
```
#### Step 3:
Add example rego policy into the file named ```example.rego```:
```
package details.authz
allow {
input.method == "GET"
employee := data.employees[_]
employee.name == input.user
employee.name == input.path[1]
}
allow {
input.method == "GET"
employee := data.employees[_]
employee.manager == input.user
employee.name == input.path[1]
}
allow {
input.method == "GET"
input.path = ["employees"]
employee := data.employees[_]
input.user == "danerys"
employee.salary > 0
employee.salary < 300000
}
```
#### Step 4:
Below cmd lets you to start opa server with mongo db and on opa server startup, we insert sample data.
```
$ docker run -d -p 9095:9095 -v /config.yaml:/opa/config.yaml /
-v /example.rego:/opa/example.rego vineeth97/opa-mongo:latest
```
### Deploying in Kubernetes:
Pre-requisites:
1. kubectl
2. kind - https://kind.sigs.k8s.io/
#### Step 1:
Create a Kubernetes cluster
```
kind create cluster
```
#### Step 2:
Running opa-mongo server with mongo database
```
kubectl create -f https://github.com/open-policy-agent/contrib/blob/master/data_filter_mongodb/k8s/opa-mongo.yaml
```
By now you have running opa-mongo server with mongo database. Now let's query the data from opa-mongo server.
### View the data that exists in mongo database:
You can view all the data that exist in the mongo database by accessing the below URL. This endpoint is exposed for viewing the data that exists in the database.
```
http://localhost:9095/records
```
This opa-mongo server is designed to retreive employee details. The employee details can be seen either by the employee or by respective manager.
Below are records that are inserted on opa server startup:
```
[
{
"Name": "john",
"Designation": "lead engineer",
"Salary": 270000,
"Email": "john@opa.com",
"Mobile": "1233743438738",
"Manager": "danerys"
},
{
"Name": "arya",
"Designation": "software engineer",
"Salary": 90000,
"Email": "arya@opa.com",
"Mobile": "1233746238738",
"Manager": "john"
},
{
"Name": "tyrian",
"Designation": "senior software engineer",
"Salary": 250000,
"Email": "tyrian@opa.com",
"Mobile": "123336238738",
"Manager": "danerys"
},
{
"Name": "jamie",
"Designation": "lead engineer",
"Salary": 70000,
"Email": "jamie@opa.com",
"Mobile": "1233746238738",
"Manager": "danerys"
},
{
"Name": "jeffrey",
"Designation": "software engineer",
"Salary": 60000,
"Email": "jeffrey@opa.com",
"Mobile": "1233746238738",
"Manager": "jamie"
},
{
"Name": "sansa",
"Designation": "senior software engineer",
"Salary": 80000,
"Email": "sansa@opa.com",
"Mobile": "1233746238738",
"Manager": "john"
},
{
"Name": "ramsay",
"Designation": "software engineer",
"Salary": 70000,
"Email": "ramsay@opa.com",
"Mobile": "1233746238738",
"Manager": "john"
},
{
"Name": "cersei",
"Designation": "senior software engineer",
"Salary": 170000,
"Email": "cersei@opa.com",
"Mobile": "1233746238738",
"Manager": "jamie"
},
{
"Name": "theon",
"Designation": "software engineer",
"Salary": 75000,
"Email": "theon@opa.com",
"Mobile": "1233746238738",
"Manager": "john"
},
{
"Name": "rob",
"Designation": "software engineer",
"Salary": 75000,
"Email": "rob@opa.com",
"Mobile": "1343238738",
"Manager": "john "
},
{
"Name": "danerys",
"Designation": "director of engineering",
"Salary": 350000,
"Email": "danerys@opa.com",
"Mobile": "12332423738",
"Manager": "nil"
}
]
```
### Querying opa-mongo server:
Below is the request you can make to opa server:
This requests for employee john details as we notice request param and path in request body says john, and the request body expects the requested user name. Based on the rego policy the requested user should be either the employee or the respective manager to retrieve the employee details.
```
URL: http://localhost:9095/employees/john
```
Request body:
```
{
"input": {
"method": "GET",
"path": ["employees", "john"],
"user": "danerys"
}
}
```
Response:
```
{
"result": {
"Defined": true,
"Data": [
{
"Name": "john",
"Designation": "lead engineer",
"Salary": 270000,
"Email": "john@opa.com",
"Mobile": "1233743438738",
"Manager": "danerys"
}
]
}
}
```
In opa-mongo server logs you can observe the received query, equivalent opa-query and the equivalent mongo-query based on the rego policy:
```
2020/08/07 18:15:45 received requestmap[method:GET path:[employees john] user:danery]
2020/08/07 18:15:45 opa-query: ["danery" = data.employees[_].name; "john" = data.employees[_].name "danery" = data.employees[_].manager; "john" = data.employees[_].name]
2020/08/07 18:15:45 mongo query: map[$or:[map[$and:[map[name:map[$eq:danery]] map[name:map[$eq:john]]]] map[$and:[map[manager:map[$eq:danery]] map[name:map[$eq:john]]]]]]
```
Now you have successfully retrevied john details by requesting the opa-mongo server by enforcing the policies from the mongo database.