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 tofalse
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 remainfalse
. - 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 ofPOST
can be used to update an existing policy template. Issuing aDELETE
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.