Open Policy Agent - OASIS - XACML March 26th 2020
Open Policy Agent - OASIS - XACML March 26th 2020
Open Policy Agent - OASIS - XACML March 26th 2020
Databases
Orchestration
1 2 3 4
UI API
CICD Pipeline Database
Container Container
sshd Host sshd Host
Cloud
Servers
Linux
Public Cloud
Open Policy Agent: Community
Inception Production Users Use Cases Today
Policy Policy
Query Decision
OPA
Input can be ANY JSON value Output can be ANY JSON value
Policy Data
(Rego) (JSON)
openpolicyagent.org
OPA: Features
Request
● Declarative Policy Language (Rego)
○ Can user X do operation Y on resource Z? Service
○ What invariants does workload W violate?
○ Which records should bob be allowed to see?
Query Decision
● Language features
○ 50+ built-in functions: JWTs, date/time, CIDR math ,etc. OPA
○ Context-aware policies (e.g., Kubernetes, AD, entitlements, etc.)
○ Composition & delegation
○ Performance optimizations (Rule Indexing, Partial Evaluation)
Policy Data
(Rego) (JSON)
● Library (Go), sidecar/host-level daemon
○ Policy and data are kept in-memory
○ Zero decision-time dependencies openpolicyagent.org
OPA: Features
Request
● Management APIs for control & observability
○ Bundle service API for sending policy & data to OPA Service
○ Status service API for receiving status from OPA
○ Log service API for receiving audit log from OPA
○ Discovery API for dynamic policy discovery & distribution Query Decision
openpolicyagent.org
Agenda
● Overview
○ Background, what is OPA?
○ Features
● Design & Architecture
○ Architecture & APIs
○ Language
Architecture: Distributed systems are the norm
● OPA serves as a host-local cache for decisions
● Policies & data cached in-memory
● No decision-time dependencies (by default)
● Leverage fate-sharing architecture
● CDN-compatible policy distribution model
control plane
POST v1/data/http/authz/allow
Service
{"input": {
"method": "GET",
"path": ["finance", "salary", "alice"],
"user": "bob"}} Query Decision
2. OPA executes policy
{“result”: true}
openpolicyagent.org
Language: IF-THEN statements
● NOT a general-purpose language. No data structures, I/O, errors, etc.
● IF-THEN statements map to real-world policies. Called "rules" in Rego.
assert allow is true if...
input.method is "GET" and...
input.resource is "/salary/{user}" and...
Remove unnecessary input.user is user.
keywords ("assert", "if",
"and", etc.) allow is true {
input.method is "GET"
input.resource is "/salary/{user}"
input.user is user Replace "is" with "=". Declare
pseudo-Rego }
variables. Use pattern
Rego allow = true { matching with JSON.
some user
input.method = "GET"
input.resource = ["salary", user]
input.user = user
} openpolicyagent.org
Language: allow is not a keyword
● Rules assign values (e.g., true) to variables (e.g., allow) based on conditions
allow = true { VARIABLE = TERM {
some user TERM = TERM
input.method = "GET" TERM = TERM OPA/Rego understands assignments,
input.resource = ["salary", user] TERM = TERM conditions, terms (values/vars), etc.
input.user = user }
}
openpolicyagent.org
Language: Collaboration is required
● Rules can refer to other rules
● Rules are namespaced and grouped in "packages"
● Conflict resolution expressed within conditions
openpolicyagent.org
Language: Decision-making requires context/data
● Document-oriented data is the norm
○ Users know the format of data in other systems
● First-class support for logic over JSON, YAML, etc.
○ Reference data with JSON Path like syntax
kubernetes
○ e.g., input.spec.containers[0].image
metadata:
● OPA/Rego can adapt to the outside world labels:
app: nginx
○ Transform incoming data name: nginx
namespace: opa
○ Build reusable domain-specific abstractions spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
volumeMounts:
- mountPath: "/var/run/serviceaccount"
name: default-token-tm9v8
openpolicyagent.org
Language: Performance is important
● Goal: policy authors should not be concerned with performance
○ Imperative languages leave global optimization up to the author
● Declarative languages focus on global optimization
○ Not turing complete
○ No side-effects
○ (Almost) order-independent
● OPA targets a range of use cases
○ E.g., API authorization requires low-latency/high-frequency decision making
○ Rule indexing and partial evaluation enable constant-time evaluation of non-linear policies
Links:
https://www.openpolicyagent.org/docs/latest/policy-performance/
https://blog.openpolicyagent.org/partial-evaluation-162750eaf422
https://blog.openpolicyagent.org/optimizing-opa-rule-indexing-59f03f17caf3
openpolicyagent.org
Thank You!
slack.openpolicyagent.org
github.com/open-policy-agent/opa
Kubernetes Policy Example OPA Playground
JSON/YAML from Kubernetes OPA Policy: All images come from a trusted registry
apiVersion: admission.k8s.io/v1beta1
kind: AdmissionReview package kubernetes.admission
request:
kind: deny[msg] {
group: '' input.request.kind.kind == "Pod"
kind: Pod
some i
version: v1
namespace: opa image := input.request.object.spec.containers[i].image
object: not startswith(image, "hooli.com")
metadata: msg := sprintf("image comes from bad registry: %v", [image])
labels: }
app: nginx
name: nginx
namespace: opa
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
volumeMounts:
- mountPath: "/var/run/serviceaccount"
openpolicyagent.org
name: default-token-tm9v8
Envoy Policy Example OPA Playground
JSON/YAML from Envoy OPA Policy: Allow all GET and some PUT
parsed_path: [“api”, “v1”, “products”]
attributes: package envoy.authz
source:
address: default permit = false
Address:
SocketAddress: # everyone can read everything
address: "172.17.0.10"
permit {
PortSpecifier:
PortValue: 36472 input.attributes.request.http.method == "GET"
destination: }
address:
Address: # writes dependent on source
SocketAddress: permit {
address: "172.17.0.17" input.attributes.request.http.method == "PUT"
PortSpecifier:
input.parsed_path = ["v1", "deployment", x]
PortValue: 9080
request: src := input.attributes.source
http: addr := src.address.Address.SocketAddress.address
id: 13359530607844510314 net.cidr_contains("172.28.0.0/16", addr)
method: GET }
headers: ...
openpolicyagent.org
path: "/api/v1/products"