{"id":18715144,"url":"https://github.com/cerbos/wit-adapter","last_synced_at":"2025-11-10T05:30:15.898Z","repository":{"id":242598292,"uuid":"809658753","full_name":"cerbos/wit-adapter","owner":"cerbos","description":"Cerbos draft WIT","archived":false,"fork":false,"pushed_at":"2024-06-18T22:08:21.000Z","size":594,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-16T20:32:43.753Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cerbos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-03T07:48:05.000Z","updated_at":"2024-06-18T22:08:24.000Z","dependencies_parsed_at":"2024-06-04T00:27:51.031Z","dependency_job_id":"525f599a-99b4-4f23-adf7-8b338f8046d1","html_url":"https://github.com/cerbos/wit-adapter","commit_stats":null,"previous_names":["cerbos/wit-adapter"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cerbos%2Fwit-adapter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cerbos%2Fwit-adapter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cerbos%2Fwit-adapter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cerbos%2Fwit-adapter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cerbos","download_url":"https://codeload.github.com/cerbos/wit-adapter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239576755,"owners_count":19662116,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T13:07:42.551Z","updated_at":"2025-11-10T05:30:15.838Z","avatar_url":"https://github.com/cerbos.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction\n\n\u003e The [WebAssembly Component Model](https://component-model.bytecodealliance.org/introduction.html) is a broad-reaching architecture for building interoperable Wasm libraries, applications, and environments\".\n\n\u003e WASI 0.2.0 was released Jan 25, 2024, providing a stable release of WASI and the component model. This is a stable set of WIT definitions that components can target. WASI proposals will continue to evolve and new ones will be introduced; however, users of the component model can now pin to the stable 0.2.0 release.\n\nThis repository describes our experience going from Core WebAssembly into WebAssembly Component Model.\n\n# Cerbos PDP and ePDP\n\n[Cerbos](https://github.com/cerbos/cerbos) is an open-core, language-agnostic, scalable authorization solution that simplifies user permissions and authorization by writing context-aware access control policies for application resources.\n\nCerbos service is a policy decision point (PDP). This repository deals with embedded Cerbos PDP (ePDP) - a free tier feature of the [Cerbos Hub](https://hub.cerbos.cloud/).\n\nAn ePDP is a self-contained program built from a set of policies that implements the [CheckResources API](https://docs.cerbos.dev/cerbos/latest/api/#check-resources).\n\nTechnically, we transpile policies to Rust code and build the WebAssembly core module. A wall clock `now` function is the only dependency ePDP has on the host.\n```rust\n#[link(wasm_import_module = \"env\")]\nextern \"C\" {\n    #[link_name = \"now\"]\n    fn now() -\u003e u64;\n}\n```\n\nThe original use cases for ePDPs include single-page applications and Node.js applications.\nIn both cases, [Cerbos JavaScript SDK](https://github.com/cerbos/cerbos-sdk-javascript/blob/main/packages/embedded/README.md) hides the low-level details of interacting with ePDP API, which is effectively a function `fn check(input: String) -\u003e String`, except that the SDK needs to allocate/deallocate memory for the strings.\nThe SDK also converts these strings (JSON serialization) to rich types, which are then exposed to the SDK client.\n\nHere, we explored converting a Wasm core module binary to a Wasm component. We are not building a component for the required policies from the source code; we build a module, which then upgrades to a component.\n\n# Make Wasm modules upgradable to the component model\n\nThe idea was to change the ePDP source code mostly incrementally. The increment must not add much to the binary size or the contract.\nWe added `wit-bindgen` crate as a dependency and the following code fragment:\n```rust\nwit_bindgen::generate!({\n    inline: r#\"\n        package cerbos-hub:epdp;\n\n        interface authorization {\n            check-wasi: func(s: string, now: u64) -\u003e string;\n        }\n        world policy {\n            export authorization;\n        }\n    \"#\n});\nstruct EPDP;\n\nimpl exports::cerbos_hub::epdp::authorization::Guest for EPDP {\n    #[doc = r\" check-wasi: func(ptr: u32, len: u32, now: s64) -\u003e u64;\"]\n    fn check_wasi(s: _rt::String, now: u64) -\u003e _rt::String {\n        policy::check_with_now(\u0026s, now as i64)\n    }\n}\nexport!(EPDP);\n```\nThe interface reflects the module's API, except that string lifting and memory management are done by the `wit-bindgen`.\n\nThe build step remained the same: `cargo build --release --target wasm32-unknown-unknown`.\nThe produced core module is compatible with the SDK. \n\n# Convert a module to a component\n\nA module can be upgraded to a Wasm component using the `wasm-tools component new` command.\nThe only problem is satisfying the core module import of the `now` function.\nWe solved this by building a core module providing a stub function:\n```bash\nrustc -o env.wasm --target wasm32-unknown-unknown --crate-type cdylib --edition=2021 \\\n -C opt-level=z -C lto -C codegen-units=1 -C debuginfo=0  - \u003c\u003cEOF\n#[no_mangle]\npub unsafe extern \"C\" fn now() -\u003e u64 { 0 }\nEOF\n```\n\nThen, create an ePDP component from an ePDP core module: `wasm-tools component new epdp-wasm.wasm -o epdp-wasi-temp.wasm --adapt ./env.wasm`.\n\n# Going from a string-based interface to a rich one\n\nHowever, we want to create an ePDP Wasm component with rich types in the interface to skip the JSON serialization/deserialization step. \nSee the DRAFT version of the [Cerbos EPDP WIT interface](wit/policy.wit). For an overview of WIT, click [here](https://component-model.bytecodealliance.org/design/wit.html).\n\nTo create a rich type component, we created a generic component, `epdp-wasi-adapter`.\n\nAs per the following diagram, `epdp-wasi-adapter` exports a rich interface and imports a simple one from the `cerbos-hub:epdp` package.\n\n![Components](Components.png)\n\nOur formula for producing a component model ePDP is `epdp-wasi = epdp-wasi-adapter + epdp-wasi-temp`, where `epdp-wasi-temp = epdp-wasm + env.wasm`.\n\nFor details on the building and composition, please refer to the [epdp-wasi-adapter/justfile](epdp-wasi-adapter/justfile).\n\n## Example\n\nIn the example, the client application `http-proxy` starts the HTTP component, and then calls the `epdp-wasi` via its rich interface.\nThe repository contains a sample version of `epdp-wasm.wasm`. You can use the Cerbos Hub to download `epdp-wasm` with your policies.\n\nPrerequisites:\n1. Rust toolchain.\n2. [wasmCloud](https://wasmcloud.com/docs/installation).\n3. [justfile](https://github.com/casey/just).\n\nLet's deploy all components to wasmCloud.\n1. From the `http-proxy` directory, run `just deploy`. To redeploy, run `just redeploy`.\n2. From the `epdp-wasi-adapter` directory, run `just start`, then `just link` to link the components. To restart, run `just restart`.\n3. Run `curl 'http://localhost:8080?role=user'` to invoke the http-proxy. You should see the `Effect::Allow`. Change the role to get `Effect::Deny`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcerbos%2Fwit-adapter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcerbos%2Fwit-adapter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcerbos%2Fwit-adapter/lists"}