2023-03-31T15:19:52-07:00: segfault.net IETF SCITT: API Emulator: Registration Policies: Simple decoupled file based policy engine

by pdxjohnny
GNU/Linux ◆ xterm-256color ◆ bash 1968 views

Pull Request: https://github.com/scitt-community/scitt-api-emulator/pull/27

$ export REC_HOSTNAME="segfault.net"; export REC_TITLE="IETF SCITT: API Emulator: Registration Policies: Simple decoupled file based policy engine"; asciinema rec --idle-time-limit 0.5 --title "$(date -Iseconds): ${REC_HOSTNAME} ${REC_TITLE}" --command "sshpass -p segfault ssh -t -o 'StrictHostkeyChecking=no' root@segfault.net tmux" "$HOME/asciinema/${REC_HOSTNAME}-rec-$(date -Iseconds).ndjson"
$ asciinema upload /home/pdxjohnny/asciinema/segfault.net-rec-2023-03-31T15:19:52-07:00.ndjson
$ python -m pip install -U pip setuptools wheel
$ echo "Clone SCITT API emulator at pinned to pdxjohnny policy_engine branch HEAD as of 2023-03-31 09:54-7:00" \
  && set -x \
  && export TARGET_DIR=scitt-api-emulator \
  && export TARGET_REPO_URL=https://github.com/scitt-community/scitt-api-emulator \
  && export TARGET_COMMIT=2787820abf3fa4701bc46a9629cd98d11254fbe6 \
  && mkdir -p "${TARGET_DIR}" \
  && cd "${TARGET_DIR}" \
  && git init \
  && git remote add origin "${TARGET_REPO_URL}" \
  && git fetch origin "${TARGET_COMMIT}" --depth 1 \
  && git reset --hard "${TARGET_COMMIT}" \
  && python -m pip install \
    --no-cache \
    -e . \
    -r dev-requirements.txt \
  && cd -
$ echo 'export PATH="${PATH}:${HOME}/.local/bin"' | tee -a ~/.bashrc
$ echo 'export PATH="${PATH}:${HOME}/.local/node_modules/.bin"' | tee -a ~/.bashrc
$ . ~/.bashrc
$ (cd ~/.local && npm install nodemon)
$ cat > enforce_policy.py <<'EOF'
import os
import sys
import pathlib

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("")
Simple drop rule based on claim content blocklist.
EOF
$ cat > is_on_blocklist.py <<'EOF'
import os
import sys
import json

import cbor2
import pycose
from pycose.messages import CoseMessage, Sign1Message

from scitt_emulator.scitt import ClaimInvalidError, COSE_Headers_Issuer

BLOCKLIST_DEFAULT = [
    "did:web:example.com",
]
BLOCKLIST_DEFAULT_JSON = json.dumps(BLOCKLIST_DEFAULT)
BLOCKLIST = json.loads(os.environ.get("BLOCKLIST", BLOCKLIST_DEFAULT_JSON))

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 msg.phdr[COSE_Headers_Issuer] not in BLOCKLIST:
    sys.exit(1)

# EXIT_SUCCESS == MUST block. In case of thrown errors/exceptions.
EOF
$ nodemon -e .cose --exec 'find workspace/storage/operations -name \*.cose -exec nohup sh -xc "echo {} && (python3 is_on_blocklist.py < {} && POLICY_ACTION=denied python3 enforce_policy.py {}) || POLICY_ACTION=insert python3 enforce_policy.py {}" \;' &
$ mkdir -p "workspace/storage/operations/"
$ timeout 1s scitt-emulator server --workspace workspace/ --tree-alg CCF --use-lro
$ echo "$(cat workspace/service_parameters.json)" \
    | jq '.insertPolicy = "external"' \
    | tee workspace/service_parameters.json.new \
    && mv workspace/service_parameters.json.new workspace/service_parameters.json
$ scitt-emulator server --workspace workspace/ --tree-alg CCF --use-lro &
$ scitt-emulator client create-claim --issuer did:web:example.com --content-type application/json --payload '{"sun": "yellow"}' --out claim.cose
$ scitt-emulator client submit-claim --claim claim.cose --out claim.receipt.cbor
... denied ...
$ scitt-emulator client create-claim --issuer did:web:example.org --content-type application/json --payload '{"sun": "yellow"}' --out claim.cose
$ scitt-emulator client submit-claim --claim claim.cose --out claim.receipt.cbor
$ echo $?
0 (aka inserted)