Wilson Mar bio photo

Wilson Mar

Hello!

Email me Calendar Skype call

LinkedIn Twitter Gitter Instagram Youtube

Github Stackoverflow Pinterest

Open Policy Agent runs queries in the Rego language

US (English)   Español (Spanish)   Français (French)   Deutsch (German)   Italiano   Português   Cyrillic Russian   中文 (简体) Chinese (Simplified)   日本語 Japanese   한국어 Korean

Overview

What is OPA?

OPA (Open Policy Agent) is purpose-built for reasoning about information represented in structured documents.

OPA is about a 20MB binary designed to be run close to the software needing policy decisions, often as a Kubernetes sidecar.

OPA has 50+ built-in functions (strings, numbers, regexps, network CIDRs, JWTs, arrays, objects, sets, etc.).

VIDEO: Gatekeeper is the subproject that integrates OPA with Kubernetes admission control.

Gatekeeper’s competition is Kyverno, which better understands Kubernetes (such as parents of resources), resource generation, easier to use, and has better reports.

Open Policy Agent provides a unified policy language – Rego – that can be enforced across the cloud-native stack (Kubernetes, Kafka, Spinnaker CI/CD, Terraform, Kong, etc.)

Rego is also used within the Kubernetes Admission Controller to validate logic in deployment descriptors before applying them to a cluster. One example of this is creating a policy that only allows deployments that reference containers from trusted repositories.

Conftest is the name of the subproject that runs OPA policies against files on a file system.

https://blog.styra.com/blog/origin-of-open-policy-agent-rego

https://github.com/open-policy-agent/opa

In AWS

BLOG: AWS Config custom rules are written in the Rego language processed by the general-purpose Open Policy Agent (OPA).

Lambda can use an OPA (Open Policy Agent) Engine to evaluate rules stored in S3.

https://github.com/aws-samples/aws-management-and-governance-samples.git (from AWS) is a collection of code samples for the Management and Governance services which includes: CloudWatch, CloudFormation, Cloudtrail, Config, Systems Manager, and more.

It contains cfn_templates (CloudFormation templates) to deploy Lambda function and AWS Config rules; lambda_sources source file for the Lambda function and the OPA binary that is a deployed as a layer for the Lambda function. Packaged sources are under the packaged_lambda_assets directory. opa_policies contains Rego policies that correspond to rules deployed by CloudFormation templates.

Rego language

Rego is described the native query language Rego for OPA processing nested documents.

Rego is declarative queries are assertions on data stored in OPA. So policy authors can focus on what queries should return rather than how queries should be executed. These queries are simpler and more concise than the equivalent in an imperative language.

The queries define policies that enumerate instances of data that violate the expected state of the system.

If all the statements in the body hold to be true, the return value is “ground” (i.e a constant).

STAR: Take the OPA Policy Authoring course by Tim Hinrichs (@tlhinrichs), CTO of Straya, OPA’s inventor.

  • https://medium.com/@mathurvarun98/how-to-write-great-rego-policies-dc6117679c9f
  • https://www.fugue.co/blog/5-tips-for-using-the-rego-language-for-open-policy-agent-opa

This sample Rego code from Docker Captain Viktor Farcic & Daring Pope in Spain, author of technologyconversations.com and books from DevopsToolkitSeries.com) gives an example:

  • In dev, no more than a 100 instances
  • Not allow “latest” tag in production

https://open-policy-agent.github.io/gatekeeper

A sample OPA file opa/block-node-port.yaml:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockNodePort
metadata:
  name: block-node-port
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Service"]

From among https://github.com/open-policy-agent/gatekeeper-library

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sblocknodeport
  annotations:
    description: Disallows all Services with type NodePort.
spec:
  crd:
    spec:
      names:
        kind: K8sBlockNodePort
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sblocknodeport
        violation[{msg: msg}] {
          input.review.kind.kind == "Service"
          input.review.object.spec.type == "NodePort"
          msg := "User is not allowed to create service of type NodePort"
        }

Let’s look at the app.yaml file containing “type: NodePort”:

apiVersion: v1
kind: service
metadata:
  name: devops-toolkit
  lables:
    app: devops-toolkit
spec:
  type: NodePort
  ports:
  - port; 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: devops-toolkit
  

When the above is enabled and this command is issued to process a yaml containing NodePort:

kubectl apply --filename app/app.yaml

These (rather redundant) messages would appear:

deployment.apps/devops-toolkit created
ingress.networking.k8s.io/devops-toolkit created
Error from server ([denited by block-not-port]) User is not allowed to create service of type NodePort): error when creating "app/app.yaml": admission webhook "validating.gatekeeper.sh" denied the request: [denied by block-node-port] User is not allowed to create service of type NodPort

The fix would be to define the NodePort to a ClusterIP:

...
spec:
  type: ClusterIP
  ...
  

OPA install

curl -L -o opa https://openpolicyagent.org/downloads/v0.31.0/opa_linux_amd64_static