# Open Policy Agent (OPA)
The OPA report allows you to define custom Policies for checking Kubernetes resources. This is useful for enforcing policies that are specific to your organization.
You may want to familiarize yourself with Rego (opens new window), the policy language used by OPA.
This page only covers OPA v2. For examples on how to write OPA v1 policies, refer to OPA v1.
# Creating OPA Policies
# Using the Insights UI
- Visit your organization's
Policy
page - Click the
Create OPA Policy
button
You'll see a sample Policy that disallows Deployments to the evil
namespace. This should give you a quick sense for
how to write OPA policies for Insights.
Insights also comes with several templates for OPA Policies which you can modify as needed. To view these templates:
- Visit your organization's
Policy
page - Navigate to the
OPA Policy Templates
page
# Using the Insights CLI
To manage policies in an infrastructure-as-code repository, you can use the Insights command-line interface (CLI). Check out OPA Policies with the CLI for more information.
# Designing OPA Policies
Each OPA policy will receive an input
parameter which contains
a Kubernetes resource.
For example, we can check to make sure that replicas
is set on all Deployments
:
package fairwinds
replicasRequired[actionItem] {
input.kind == "Deployment"
input.spec.replicas == 0
actionItem := {}
}
The actionItem
object is what Insights will examine to determine the details of the
issue. The following fields can be set:
title
- String - a short title for the Action Itemdescription
- String - a longer description of the issue. Can include markdownremediation
- String - instructions for fixing the issue. Can include markdowncategory
- String - valid values areSecurity
,Efficiency
orReliability
severity
- Integer - between 0.0 and 1.0.
Action Item severity is defined as:
- 0.0 - None
- 0.1 to 0.39 - Low
- 0.4 to 0.69 - Medium
- 0.7 to .89 - High
- 0.9 to 1.0 - Critical
For instance, in the above OPA policy we could set:
package fairwinds
replicasRequired[actionItem] {
input.kind == "Deployment"
input.spec.replicas == 0
actionItem := {
"title": concat(" ", [input.kind, "does not have replicas set"]),
"description": "All workloads at acme-co must explicitly set the number of replicas",
"remediation": "Please set `spec.replicas`",
"category": "Reliability",
"severity": 0.5
}
}
# Varying Action Item Attributes
You can reuse the same OPA policy, setting different Action Item attributes for different cases.
For instance, say we wanted to apply our replicas
policy above to both Deployment
and StatefulSet
but wanted a higher severity for Deployments
:
package fairwinds
replicasRequired[actionItem] {
# List the Kubernetes Kinds to which this policy should apply.
kinds := {"Deployment", "StatefulSet"}
# List severities for each of the above Kinds. Kind.
severityByKind := {
"StatefulSet": 0.4,
"Deployment": 0.9,
}
# Iterate Kinds{} and only continue if input.kind is one of them.
kind := kinds[val]
input.kind == kind
input.spec.replicas == 0
# Set the severity based on the Kind.
dynamicSeverity := severityByKind[input.kind]
actionItem := {
"title": concat(" ", [input.kind, "does not have replicas set"]),
"description": "All workloads at acme-co must explicitly set the number of replicas",
"remediation": "Please set `spec.replicas`",
"category": "Reliability",
"severity": dynamicSeverity,
}
}
# Restricting OPA Policies by Insights Context
By default an OPA policy will run in all available contexts. These contexts are:
- Insights Agent
- Admission Controller
- CI Integration
However, you can restrict an OPA policy to only run in certain Insights contexts using the insightsinfo()
Rego function
and the Agent
, Admission
and CI/CD
values:
context := insightsinfo("context")
# List the Insights contexts in which this policy should apply.
validContexts := {"Admission", "Agent"}
# Only continue if the policy is executing in one of validContexts{}
validContext := validContexts[val]
context == validContext
# Varying Execution by Kubernetes Clusters
By default an OPA policy will run in all available clusters. You can restrict an OPA policy to run in specific Kubernetes clusters:
# List the Kubernetes clusters to which this policy should apply.
validClusters := {"cluster1", "cluster2"}
# Only continue if the policy is executing in one of validClusters{}
cluster := insightsinfo("cluster")
validCluster := validClusters[val]
cluster == validCluster
# Varying Execution by Admission Request Properties
You can restrict an OPA policy to run based on several admissionRequest properties.
Accessible via insightsinfo("admissionRequest")
Rego function:
# List of admission request operations to which this policy should apply.
validOperations := {"CREATE"}
# Only continue if the policy is executing in one of validOperations list
operation := insightsinfo("admissionRequest").operation
validOperation := validOperations[val]
operation == validOperation
# Variable Parameters
If we want:
- Deployments to have at least three replicas
- StatefulSets to have at least one replica
we can vary this value based on the Kubernetes Kind:
package fairwinds
replicasRequired[actionItem] {
# List the Kubernetes Kinds to which this policy should apply.
kinds := {"Deployment", "StatefulSet"}
# List the minimum required replicas for each of the above Kinds.
minReplicasByKind := {
"StatefulSet": 1,
"Deployment": 3,
}
# Iterate Kinds{} and only continue if input.kind is one of them.
kind := kinds[val]
input.kind == kind
minReplicas := minReplicasByKind[input.kind]
input.spec.replicas < minReplicas
actionItem := {
"title": sprintf("%s must have a minimum of %d replicas", [input.kind, minReplicas]),
"description": "Workloads at acme-co must have minimum number of replicas",
"remediation": "Please set `spec.replicas` appropriately",
"category": "Reliability",
"severity": 0.2,
}
}
# Using the Kubernetes API
You can cross-check OPA policy input with Kubernetes objects from the cluster at Policy execution time. For example, this ensures that all Deployments
have an associated HorizontalPodAutoscaler
:
package fairwinds
hasMatchingHPA(hpas, elem) {
hpa := hpas[_]
hpa.spec.scaleTargetRef.kind == elem.kind
hpa.spec.scaleTargetRef.name == elem.metadata.name
hpa.metadata.namespace == elem.metadata.namespace
hpa.spec.scaleTargetRef.apiVersion == elem.apiVersion
}
hpaRequired[actionItem] {
not hasMatchingHPA(kubernetes("autoscaling", "HorizontalPodAutoscaler"), input)
actionItem := {
"title": "No horizontal pod autoscaler found"
}
}
# Testing OPA Policies
After uploading a new Policy, it's good to test that it is working properly. To do so you can manually kick off a report:
kubectl create job opa-test --from cronjob/opa -n insights-agent
Watch the pod logs for the resulting Job
to spot any potential errors in your OPA policy.
The Insights CLI also facilitates offline testing of OPA policies. Check out the Validating OPA policy documentation.
# Adding Resources to OPA Policies
The Insights OPA plugin executes OPA policies for these Kubernetes resources by default:
- Deployment
- DaemonSet
- StatefulSet
- Pod
- Job
- CronJob
If you'd like to add additional resources, you can use the opa.targetResources
from the
Insights Agent Helm chart (opens new window):
opa:
enabled: true
targetResources:
- apiGroups:
- networking.k8s.io
resources:
- ingress
By default the OPA plugin inherits the same Kubernetes APIGroups and Resources defined in the default rules for the Admission Controller.