Skip to content

Add the DLS OPA access policy from diamond-tiled - #14

Merged
gilesknap merged 2 commits into
mainfrom
dls-access-policy
Oct 13, 2026
Merged

gilesknap merged 2 commits into
mainfrom
dls-access-policy

Conversation

@gilesknap

@gilesknap gilesknap commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Ports DiamondOpenPolicyAgentAuthorizationPolicy from Zoheb Shaikh's diamond-tiled (diamond_policy/dls.py, commit 236f4d3) into the package as dls_tiled.policy, so dls-tiled covers everything diamond-tiled provides. diamond-tiled loads the file from /deploy/config on sys.path; here it is installed in tiled's venv, so a config only changes the module path. Zoheb is credited as co-author on the commit and in the README.

What the policy does

An ExternalPolicyDecisionPoint that asks Open Policy Agent for every decision. The OPA input is the user's access token, the token audience, and either the node's proposal/visit/beamline (from a JSON tag in the access_blob) or its session (from an integer tag). filters, init_node and modify_node reject None and non-user principals with 401. filters maps OPA's ["*"] to all access. init_node stores the tag that OPA returns. allowed_scopes is inherited from tiled unchanged.

Adaptations from the original

None to the logic. The file passes ruff, ruff format and pyright (standard mode) unchanged, and every import and override signature matches tiled 0.2.18: ExternalPolicyDecisionPoint, ResultHolder, ALL_ACCESS/NO_ACCESS, AccessBlobFilter, Principal.access_token and PrincipalType are all present, and the base __init__ takes the same keyword arguments. The only addition is a module docstring with the attribution. The original builds against tiled main; nothing in it needed main-only API.

Config

access_control:
  access_policy: dls_tiled.policy:DiamondOpenPolicyAgentAuthorizationPolicy
  args:
    authorization_provider: http://opa:8181/v1/data/  # needs the trailing /
    token_audience: account
    create_node_endpoint: tiled/user_session
    allowed_tags_endpoint: tiled/user_sessions
    scopes_endpoint: tiled/scopes
    modify_node_endpoint: tiled/modify_session
    empty_access_blob_public: true
    provider: null

diamond-tiled has no access_control: example (its chart values do not set one), so the authorization_provider and token_audience values above are placeholders.

Changes

  • src/dls_tiled/policy.py: the policy.
  • tests/test_policy.py: 29 tests, 100% coverage of the module. They cover build_input (DiamondAccessBlob, int session, first tag only, no tags, an unparseable tag, no token, a service principal), the 401 principal checks, and filters, init_node, modify_node and allowed_scopes against a mocked OPA (httpx.MockTransport, so no new dev dependency). They also load the policy through tiled.config.parse_configs with every argument set. Async tests use anyio's pytest plugin, which is already installed.
  • Dockerfile: the smoke check also imports dls_tiled.policy.
  • README.md: a "DLS access policy" section.
  • Charts/tiled/values.yaml: a commented opt-in example next to the routers comment.

Points to confirm (behaviour carried over unchanged)

  • empty_access_blob_public defaults to true, so a node created with no access_blob is allowed without asking OPA.
  • allowed_scopes (inherited) does not check the principal, so OPA is asked without a token for anonymous requests.
  • A tag that is neither an int nor a full proposal/visit/beamline object raises a pydantic ValidationError (a ValueError). On create or modify, tiled turns that into a 403; when a node whose stored tag is malformed is read (allowed_scopes, filters), it is a 500.
  • The OPA rule semantics (endpoint names and result shapes) come from the code only and have not been tested against a live DLS OPA bundle.

Checks run locally: pre-commit on all files, pytest (33 passed), and pyright on src and tests. No container runtime was available locally, so the image build is left to CI.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CCtPFejfd3WP589miPqaL3

Port DiamondOpenPolicyAgentAuthorizationPolicy from diamond-tiled's
diamond_policy/dls.py into the package as dls_tiled.policy, so the image
can be configured with

    access_control:
      access_policy: dls_tiled.policy:DiamondOpenPolicyAgentAuthorizationPolicy

The policy logic is unchanged; it already builds against tiled 0.2.18.
Add unit tests against a mocked OPA, import the module in the image
smoke check, and document it in the README and the chart values.

Co-Authored-By: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CCtPFejfd3WP589miPqaL3
@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.00%. Comparing base (851115d) to head (b916690).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #14      +/-   ##
==========================================
+ Coverage   61.64%   70.00%   +8.35%     
==========================================
  Files           3        4       +1     
  Lines         219      280      +61     
==========================================
+ Hits          135      196      +61     
  Misses         84       84              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

tiled clients send access_blob {} by default, so only an explicit null
skips OPA.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CCtPFejfd3WP589miPqaL3
@gilesknap
gilesknap merged commit e78b754 into main Oct 13, 2026
8 checks passed
@gilesknap
gilesknap deleted the dls-access-policy branch October 13, 2026 10:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant