This repository was archived by the owner on Nov 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Simple decoupled file based policy engine #27
Merged
Merged
Changes from 12 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
f77b512
Simple file presence based policy evaluation
pdxjohnny 07a63a3
Document simple decoupled file based policy engine
pdxjohnny 4c386b8
Tests for simple decoupled file based policy engine
pdxjohnny 84efde5
asciicast example simple decoupled file based policy engine for docum…
pdxjohnny a46d35e
Implement reason communication associated with policy enforcement
pdxjohnny ad8aed3
docs: registration_policies: Leverage jsonschema for evaluation of claim
pdxjohnny 00087fd
docs: registration_policies: Decode COSE messages payload before JSON…
pdxjohnny c6fdd26
Add jsonschema to dev-requirements.txt
pdxjohnny bd059a8
docs: registration_policies: Add policy_engine.sh wrapper and source …
pdxjohnny f11c771
Add jsonschema to envrionment.yml
pdxjohnny 4742605
docs: registration_polices: Convert example from blocklist to allowli…
pdxjohnny 24b8fb2
docs: registration_policies: Fix policy_engine.sh wrarper to remove e…
pdxjohnny 3806008
tests: docs: Support for conda test execution via addition of PYTHONPATH
pdxjohnny File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| pyOpenSSL | ||
| pytest | ||
| jsonschema | ||
| requests==2.31.0 | ||
| requests-toolbelt==0.9 | ||
| urllib3<2.0.0 | ||
| myst-parser |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| # Registration Policies | ||
|
|
||
| - References | ||
| - [5.2.2. Registration Policies](https://www.ietf.org/archive/id/draft-birkholz-scitt-architecture-02.html#name-registration-policies) | ||
|
|
||
| ## Simple decoupled file based policy engine | ||
|
|
||
| The SCITT API emulator can deny entry based on presence of | ||
| `operation.policy.{insert,denied,failed}` files. Currently only for use with | ||
| `use_lro=True`. | ||
|
|
||
| This is a simple way to enable evaluation of claims prior to submission by | ||
| arbitrary policy engines which watch the workspace (fanotify, inotify, etc.). | ||
|
|
||
| [](https://asciinema.org/a/572766) | ||
|
|
||
| Start the server | ||
|
|
||
| ```console | ||
| $ rm -rf workspace/ | ||
| $ mkdir -p workspace/storage/operations | ||
| $ scitt-emulator server --workspace workspace/ --tree-alg CCF --use-lro | ||
| Service parameters: workspace/service_parameters.json | ||
| ^C | ||
| ``` | ||
|
|
||
| Modification of config to non-`*` insert policy. Restart SCITT API emulator server after this. | ||
|
|
||
| ```console | ||
| $ echo "$(cat workspace/service_parameters.json)" \ | ||
| | jq '.insertPolicy = "allowlist.schema.json"' \ | ||
| | tee workspace/service_parameters.json.new \ | ||
| && mv workspace/service_parameters.json.new workspace/service_parameters.json | ||
| { | ||
| "serviceId": "emulator", | ||
| "treeAlgorithm": "CCF", | ||
| "signatureAlgorithm": "ES256", | ||
| "serviceCertificate": "-----BEGIN CERTIFICATE-----", | ||
| "insertPolicy": "allowlist.schema.json" | ||
| } | ||
| ``` | ||
|
|
||
| Basic policy engine in two files | ||
|
|
||
| **enforce_policy.py** | ||
|
|
||
| ```python | ||
| import os | ||
| import sys | ||
| import pathlib | ||
|
|
||
| policy_reason = "" | ||
| if "POLICY_REASON_PATH" in os.environ: | ||
| policy_reason = pathlib.Path(os.environ["POLICY_REASON_PATH"]).read_text() | ||
|
|
||
| cose_path = pathlib.Path(sys.argv[-1]) | ||
| policy_action_path = cose_path.with_suffix(".policy." + os.environ["POLICY_ACTION"].lower()) | ||
| policy_action_path.write_text(policy_reason) | ||
| ``` | ||
|
|
||
| Simple drop rule based on claim content allowlist. | ||
|
|
||
| **allowlist.schema.json** | ||
|
|
||
| ```json | ||
| { | ||
| "$id": "https://schema.example.com/scitt-allowlist.schema.json", | ||
| "$schema": "https://json-schema.org/draft/2020-12/schema", | ||
| "properties": { | ||
| "issuer": { | ||
| "type": "string", | ||
| "enum": [ | ||
| "did:web:example.org" | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| **jsonschema_validator.py** | ||
|
|
||
| ```python | ||
| import os | ||
| import sys | ||
| import json | ||
| import pathlib | ||
| import traceback | ||
|
|
||
| import cbor2 | ||
| import pycose | ||
| from jsonschema import validate, ValidationError | ||
| from pycose.messages import CoseMessage, Sign1Message | ||
|
|
||
| from scitt_emulator.scitt import ClaimInvalidError, COSE_Headers_Issuer | ||
|
|
||
| claim = sys.stdin.buffer.read() | ||
|
|
||
| msg = CoseMessage.decode(claim) | ||
|
|
||
| if pycose.headers.ContentType not in msg.phdr: | ||
| raise ClaimInvalidError("Claim does not have a content type header parameter") | ||
| if COSE_Headers_Issuer not in msg.phdr: | ||
| raise ClaimInvalidError("Claim does not have an issuer header parameter") | ||
|
|
||
| if not msg.phdr[pycose.headers.ContentType].startswith("application/json"): | ||
| raise TypeError( | ||
| f"Claim content type does not start with application/json: {msg.phdr[pycose.headers.ContentType]!r}" | ||
| ) | ||
|
|
||
| SCHEMA = json.loads(pathlib.Path(os.environ["SCHEMA_PATH"]).read_text()) | ||
|
|
||
| try: | ||
| validate( | ||
| instance={ | ||
| "$schema": "https://schema.example.com/scitt-policy-engine-jsonschema.schema.json", | ||
| "issuer": msg.phdr[COSE_Headers_Issuer], | ||
| "claim": json.loads(msg.payload.decode()), | ||
| }, | ||
| schema=SCHEMA, | ||
| ) | ||
| except ValidationError as error: | ||
| print(str(error), file=sys.stderr) | ||
| sys.exit(1) | ||
| ``` | ||
|
|
||
| We'll create a small wrapper to serve in place of a more fully featured policy | ||
| engine. | ||
|
|
||
| **policy_engine.sh** | ||
|
|
||
| ```bash | ||
| export SCHEMA_PATH="${1}" | ||
| CLAIM_PATH="${2}" | ||
|
|
||
| echo ${CLAIM_PATH} | ||
|
|
||
| (python3 jsonschema_validator.py < ${CLAIM_PATH} 2>error && POLICY_ACTION=insert python3 enforce_policy.py ${CLAIM_PATH}) || (python3 -c 'import sys, json; print(json.dumps({"type": "denied", "detail": sys.stdin.read()}))' < error > reason.json; POLICY_ACTION=denied POLICY_REASON_PATH=reason.json python3 enforce_policy.py ${CLAIM_PATH}) | ||
| ``` | ||
|
|
||
| Example running allowlist check and enforcement. | ||
|
|
||
| ```console | ||
| $ npm install -g nodemon | ||
| $ nodemon -e .cose --exec 'find workspace/storage/operations -name \*.cose -exec nohup sh -xe policy_engine.sh $(cat workspace/service_parameters.json | jq -r .insertPolicy) {} \;' | ||
| ``` | ||
|
|
||
| Also ensure you restart the server with the new config we edited. | ||
|
|
||
| ```console | ||
| $ scitt-emulator server --workspace workspace/ --tree-alg CCF --use-lro | ||
| ``` | ||
|
|
||
| Create claim from allowed issuer (`.org`) and from non-allowed (`.com`). | ||
|
|
||
| ```console | ||
| $ scitt-emulator client create-claim --issuer did:web:example.com --content-type application/json --payload '{"sun": "yellow"}' --out claim.cose | ||
| Claim written to claim.cose | ||
| $ scitt-emulator client submit-claim --claim claim.cose --out claim.receipt.cbor | ||
| Traceback (most recent call last): | ||
| File "/home/alice/.local/bin/scitt-emulator", line 33, in <module> | ||
| sys.exit(load_entry_point('scitt-emulator', 'console_scripts', 'scitt-emulator')()) | ||
| File "/home/alice/Documents/python/scitt-api-emulator/scitt_emulator/cli.py", line 22, in main | ||
| args.func(args) | ||
| File "/home/alice/Documents/python/scitt-api-emulator/scitt_emulator/client.py", line 196, in <lambda> | ||
| func=lambda args: submit_claim( | ||
| File "/home/alice/Documents/python/scitt-api-emulator/scitt_emulator/client.py", line 107, in submit_claim | ||
| raise_for_operation_status(operation) | ||
| File "/home/alice/Documents/python/scitt-api-emulator/scitt_emulator/client.py", line 43, in raise_for_operation_status | ||
| raise ClaimOperationError(operation) | ||
| scitt_emulator.client.ClaimOperationError: Operation error denied: 'did:web:example.com' is not one of ['did:web:example.org'] | ||
|
|
||
| Failed validating 'enum' in schema['properties']['issuer']: | ||
| {'enum': ['did:web:example.org'], 'type': 'string'} | ||
|
|
||
| On instance['issuer']: | ||
| 'did:web:example.com' | ||
|
|
||
| $ scitt-emulator client create-claim --issuer did:web:example.org --content-type application/json --payload '{"sun": "yellow"}' --out claim.cose | ||
| Claim written to claim.cose | ||
| $ scitt-emulator client submit-claim --claim claim.cose --out claim.receipt.cbor | ||
| Claim registered with entry ID 1 | ||
| Receipt written to claim.receipt.cbor | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,3 +34,5 @@ dependencies: | |
| - rkvst-archivist==0.20.0 | ||
| - six==1.16.0 | ||
| - urllib3<2.0.0 | ||
| - myst-parser==1.0.0 | ||
| - jsonschema==4.17.3 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.