Skip to content

Delta Bundles #1055

Description

@tsandall

The bundle protocol is designed around polling and snapshots. As a result, bundles are not well-suited for cases that require fast propagation of policy and data changes and/or small changes to large snapshots.

To address these issues we could extend OPA and the bundle protocol to support:

  1. Long-lived HTTP connections that serve bundles and bundle deltas.
  2. Delta-based bundles that contain patches to policy and data instead of snapshots.

By combining long-lived HTTP connections that stream bundle deltas to clients, bundle services can propagate changes to OPAs quickly and efficiently.

Example HTTP interaction

GET /bundles/examplia/gratia HTTP/1.1
If-None-Match: "etag-or-revision-of-successful-activation"
Prefer: stream
HTTP/1.1 200 OK
Content-Type: application/vnd.openpolicyagent.bundles
Transfer-Encoding: chunked
ETag: "etag-of-new-bundle"
Cache-Control: max-age=300

Details:

  • The message body contains stream of snapshot and delta bundles.
  • The chunk size specifies the size of the bundle.
  • If the connection between the client and server is closed for any reason, the client will reconnect using the etag/revision of the last successful activation (this is the current behaviour.)

Differences from existing protocol:

  • Client includesPrefer: stream HTTP header
  • Server replies with application/vnd.openpolicyagent.bundles if streaming is supported.

If the client specifies Prefer: stream and the server does not support it, the client will fallback to polling.

Delta bundles

We'll introduce a new kind of bundle that encodes a series of data patch and policy update operations. Delta bundles have the same structure and layout semantics as snapshot bundles. Differences between snapshot and delta bundles:

  • Clients will read patch.json files out of delta bundles. patch.json files will contain a JSON Patch (i.e., an array of JSON objects.) The operations in the JSON Patch will be applied to OPA's in-memory store in order. The JSON Patch sets will be applied in alphabetical order (e.g., a/b/c/patch.json will be applied before a/b/c/d/patch.json.)
  • Clients will insert or update policies inside the delta bundle. Policies that are not listed in the delta bundle will be carried over from the previous bundle.
  • Clients will remove policies listed in the manifest (e.g., {"removed_policies": ["path/to/policy.rego"], ...})
  • Clients will use the "revision" value from the manifest for the If-None-Match header when executing subsequent bundle GET requests.

Example Delta Bundle

patch.json
.manifest

patch.json:

[
  {"op": "add", "path": "/roles/foo", "value": {"method": "get", "path": "widgets"}}
]

Open Questions

  • It's not immediately clear how this feature would work with bundle signatures (Signature support in OPA bundles #1757). The initial implementation does not have to address this but the design should account for it.

Metadata

Metadata

Labels

Type

No type

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions