Skip to main content
Version: v4.13

Rego Policy Samples

Policy Template Creation

The first step in creating a Rego Policy is that you must first create a policy template. We will start with the following simple Rego code.

policyConditions = {
"activityTypes": ["query"],
"inclusions": [
{
"userId": "blocked_user"
}
]
}

policyApplies {
input.activityLogs.client.host != "1.1.1.1"
}

default policyDecision = {}

policyDecision = {
"requestViolation": {
"actions": {
"alert": true,
"block": false,
},
"cause": "Blocked User Detected",
"severity": "low"
}
} {
policyApplies
}

The policyConditions will make sure this policy template is only evaluated against requests that the sidecar considers a query and if the endUser is blocked_user.

The policyApplies test is checking whether the client.host connecting to the sidecar is not set to 1.1.1.1. If the query is from any host other than 1.1.1.1, then policyApplies will evaluate to true. Otherwise, it will evaluate to false.

The policy evaluator is looking for policyDecision to contain data AND for that data to match the structure noted above. In the example above, default value is set to {} so the policy allows this activity without any restrictions. We then perform the check of policyDecision = { ... } { policyApplies } to set policyDecision only if policyApplies evaluates to true.

The result of this basic policy template would be to generate a policy violation alert of Blocked User Detected with a severity of low. If we wanted this policy to block the user, then block should be changed to true like in the example below.

policyConditions = {
"activityTypes": ["query"],
"inclusions": [
{
"userId": "blocked_user"
}
]
}

policyApplies {
input.activityLogs.client.host != "1.1.1.1"
}

default policyDecision = {}

policyDecision = {
"requestViolation": {
"actions": {
"alert": true,
"block": true,
},
"cause": "Blocked User Detected",
"severity": "low"
}
} {
policyApplies
}

Allow Parameters to the Policy Template

While the above code is quite useful, it is very static and does not allow us to customize this for reuse in multiple policies. In order to make this more useful in policies, we will add some configurable items to the policy template:

policyConditions = {
"activityTypes": ["query"],
"inclusions": [
{
"userId": data.policyParams.blocked_user
}
]
}

default block = false

block {
data.policyParams.block
}

policyApplies {
input.activityLogs.client.host != data.policyParams.client_host_ip
}

default policyDecision = {}

policyDecision = {
"requestViolation": {
"actions": {
"alert": true,
"block": block,
},
"cause": "Blocked User Detected",
"severity": data.policyParams.alertSeverity
}
} {
policyApplies
}

This template has the following updates:

  • Line 5 : This is changing our endUser search to be read from the policy parameters.
  • Line 10 : This is defining a new variable called block that is set to false by default so that the policy does not block any traffic.
  • Lines 12 - 14 : This is reading the block parameter from the policy configuration. If the value is not provide, then it’ll remain false.
  • Line 17 : This is changing our client.host search to be read from the policy parameters.
  • Line 26 : Now the decision to block the request is controlled by the block variable.
  • Line 29 : This allows the severity level to be configured by the policy parameters.

The logic of the rule is not changed at this point but it does allow for reuse.

Creating a Policy Parameters Schema

Now that the policy is allowing parameters, you will also need to make sure that there is suitable validation of those parameters for policy creation. Following is an example JSON schema that can be used for this purpose.

{
"$schema": "http://json-schema.org/schema#",
"$id": "http://www.your.site/schemas/example-paramschema.json",
"type": "object",
"properties": {
"block": {
"type": "boolean",
"default": false
},
"blocked_user" : {
"type": "string",
"minLength": 1
},
"client_host_ip" : {
"type": "string",
"minLength": 1
},
"alertSeverity": {
"type": "string",
"enum": [
"low",
"medium",
"high"
]
}
},
"allOf": [
{
"required": [
"alertSeverity",
"blocked_user",
"client_host_ip"
]
}
]
}

The $schema and type are fixed and should be the same across any policy templates that are created. The $id should be unique to each policy template as a best practice and does not need to be a valid location.

The properties block is required and is used to define what parameters are accepted into the policy template. The keys in the properties object should be the name of each parameter. We have defined the block, blocked_user, client_host_ip, and alertSeverity parameters that we’re using in the policy template example.

The allOf is defining which parameters are required in a policy that uses the template. In this case, we require the blocked_user, client_host_ip, and alertSeverity parameters to be defined in any created policy.

NOTE: Additional details regarding this schema are outside the scope of this document. You can review the Understanding JSON Schema — Understanding JSON Schema 2020-12 documentation page for additional details.

Adding the Policy Template to the Cyral Control Plane

With the rego policy and schema defined, you are now able to put the policy template into the Cyral Control Plane to be used for the creation of policies. In order to create the policy template in the Cyral Control Plane, you need to make a POST request to the /v1/regopolicies/templates/USER_DEFINED endpoint.

NOTE: Issuing a PUT request instead of POST can be used to update an existing policy template. Issuing a DELETE can be used to delete a policy template.

The payload of the request should follow the below format

{
"codeBlob": "string",
"description": "string",
"name": "string",
"override": false,
"parametersSchema": "string",
"tags": [
"string"
],
"version": "string"
}

Most of the fields are self explanatory except for the codeBlob and parametersSchema fields. These fields are JSON encoded strings of our Rego code (codeBlob) and the JSON parameter schema (parametersSchema) defined above. Below is an example JSON payload using our example code from above:

{
"codeBlob": "policyConditions = {\n\t\"activityTypes\": [\"query\"],\n\t\"inclusions\": [\n {\n \"userId\": data.policyParams.blocked_user\n }\n\t]\n}\n\ndefault block = false\n\nblock {\n\tdata.policyParams.block\n}\n\npolicyApplies {\n\tinput.activityLogs.client.host != data.policyParams.client_host_ip\n}\n\ndefault policyDecision = {}\n\npolicyDecision = {\n\t\"requestViolation\": {\n\t\t\"actions\": {\n\t\t\t\"alert\": true,\n\t\t\t\"block\": block,\n\t\t},\n\t\t\"cause\": \"Blocked User Detected\",\n\t\t\"severity\": data.policyParams.alertSeverity\n\t}\n} {\n\tpolicyApplies\n}\n",
"description": "This is an example policy template that can be used to block a specific user",
"name": "Policy to Block a Specific User",
"override": false,
"parametersSchema": "{\n \"$schema\": \"http://json-schema.org/schema#\",\n \"$id\": \"http://www.customer.domain/schemas/example-paramschema.json\",\n \"type\": \"object\",\n \"properties\": {\n \"block\": {\n \"type\": \"boolean\",\n \"default\": false\n },\n \"blocked_user\" : {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"alertSeverity\": {\n \"type\": \"string\",\n \"enum\": [\n \"low\",\n \"medium\",\n \"high\"\n ]\n }\n },\n \"allOf\": [\n {\n \"required\": [\n \"alertSeverity\",\n \"blocked_user\"\n ]\n }\n ]\n}\n",
"tags": [
"Security"
],
"version": "v1.0.0"
}

The POST request would look something like

curl -X POST https://customer.control.plane/v1/regopolicies/templates/USER_DEFINED -H "authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" -d '{
"codeBlob": "policyConditions = {\n\t\"activityTypes\": [\"query\"]\n}\n\ndefault block = false\n\nblock {\n\tdata.policyParams.block\n}\n\npolicyApplies {\n\tinput.activityLogs.identity.endUser == data.policyParams.blocked_user\n}\n\ndefault policyDecision = {}\n\npolicyDecision = {\n\t\"requestViolation\": {\n\t\t\"actions\": {\n\t\t\t\"alert\": true,\n\t\t\t\"block\": block,\n\t\t},\n\t\t\"cause\": \"Blocked User Detected\",\n\t\t\"severity\": data.policyParams.alertSeverity\n\t}\n} {\n\tpolicyApplies\n}\n",
"description": "This is an example policy template that can be used to block a specific user",
"name": "Policy to Block a Specific User",
"override": false,
"parametersSchema": "{\n \"$schema\": \"http://json-schema.org/schema#\",\n \"$id\": \"http://www.your.site/schemas/example-paramschema.json\",\n \"type\": \"object\",\n \"properties\": {\n \"block\": {\n \"type\": \"boolean\",\n \"default\": false\n },\n \"blocked_user\" : {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"client_host_ip\" : {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"alertSeverity\": {\n \"type\": \"string\",\n \"enum\": [\n \"low\",\n \"medium\",\n \"high\"\n ]\n }\n },\n \"allOf\": [\n {\n \"required\": [\n \"alertSeverity\",\n \"blocked_user\",\n \"client_host_ip\"\n ]\n }\n ]\n}\n",
"tags": [
"Security"
],
"version": "v1.0.0"
}'

The result from the Control Plane would be similar to:

{
"id": "2Rbo...FkMM",
"category": "USER_DEFINED"
}

The id in the response will be used as the templateId when creating policies.

Creating a Policy Using the Template

With the policy template added in the Control Plane, you can now create policies that will enforce what is in the template. Creating a policy requires a POST request to the /v1/regopolicies/instances/USER_DEFINED endpoint. The payload of the request should be in the following format

{
"instance": {
"description": "string",
"enabled": true,
"name": "string",
"parameters": "string",
"scope": {
"repoIds": [
"string"
]
},
"tags": [
"string"
],
"templateId": "string"
}
}

Again, most of these fields are self explanatory. The parameters field should be a JSON encode string that contains the policy parameters that are defined in the policy template. The scope.repoIds array will be a list of repository Ids where this policy should be applied. The templateId should be the id received in the response when creating the policy template. Continuing with our example, our POST would look something like the following.

{
"instance": {
"description": "This policy will block the restricted_user in two of our repos",
"enabled": true,
"name": "Block restricted_user",
"parameters": "{\"block\": true,\"blocked_user\": \"restricted_user\",\"alertSeverity\":\"medium\"}",
"scope": {
"repoIds": [
"abcd...1234",
"wxyz...6789"
]
},
"tags": [
"Security"
],
"templateId": "block-user-access"
}
}

The POST request would look something like

curl -X POST https://customer.control.plane/v1/regopolicies/instances/USER_DEFINED -H "authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" -d '{
"instance": {
"description": "This policy will block the restricted_user in two of our repos",
"enabled": true,
"name": "Block restricted_user",
"parameters": "{\"client_host_ip\":\"1.1.1.1\",\"block\": true,\"blocked_user\": \"restricted_user\",\"alertSeverity\":\"medium\"}",
"scope": {
"repoIds": [
"abcd...1234",
"wxyz...6789"
]
},
"tags": [
"Security"
],
"templateId": "2Rbo...FkMM"
}
}'

The result from the Control Plane would be similar to:

{
"id": "2R...IU",
"category": "USER_DEFINED"
}

The id included in this response is the policyID and can be used in future updates to this policy.

Read Policy Instances

In order to Read the policy, we issue a GET request to the /v1/regopolicies/instances/USER_DEFINED endpoint.

Read A Specific Policy Instance

A GET request to the URI /v1/regopolicies/instances/USER_DEFINED/<policyID> will return the policy specified.

Read All Policy Instances

A GET request to the URI /v1/regopolicies/instances/USER_DEFINED will return all of the existing Rego policies.

Update a Policy Instance

In order to UPDATE a policy, make a PUT request to URI /v1/regopolicies/instances/USER_DEFINED/<policyID> with a payload similar to that for the POST request.

Delete a Policy Instance

Make a DELETE request to URI /v1/regopolicies/instances/USER_DEFINED/<policyID> in order to delete a policy instance.