diff --git a/docs/assets/cedarling-add-policy.png b/docs/assets/cedarling-add-policy.png new file mode 100644 index 00000000000..84d895b35d2 Binary files /dev/null and b/docs/assets/cedarling-add-policy.png differ diff --git a/docs/assets/cedarling-copylink.png b/docs/assets/cedarling-copylink.png new file mode 100644 index 00000000000..47c34c98fd7 Binary files /dev/null and b/docs/assets/cedarling-copylink.png differ diff --git a/docs/assets/cedarling-policy-designer.png b/docs/assets/cedarling-policy-designer.png new file mode 100644 index 00000000000..c6d76f653df Binary files /dev/null and b/docs/assets/cedarling-policy-designer.png differ diff --git a/docs/assets/cedarling-policy-store-name.png b/docs/assets/cedarling-policy-store-name.png new file mode 100644 index 00000000000..f1a37492b02 Binary files /dev/null and b/docs/assets/cedarling-policy-store-name.png differ diff --git a/docs/assets/cedarling-select-repo.png b/docs/assets/cedarling-select-repo.png new file mode 100644 index 00000000000..4a5f822e0bd Binary files /dev/null and b/docs/assets/cedarling-select-repo.png differ diff --git a/docs/cedarling/cedarling-binding-types.md b/docs/cedarling/cedarling-binding-types.md index f00ab854c05..8d4dc1b8f46 100644 --- a/docs/cedarling/cedarling-binding-types.md +++ b/docs/cedarling/cedarling-binding-types.md @@ -6,14 +6,23 @@ tags: # Bindings Offered by Cedarling -## This content is in progress +Cedarling bindings offer ways to integrate Cedarling with apps running in +various execution environments. -The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. +## Browser apps -## Have questions in the meantime? +Cedarling can run in a browser alongside JavaScript +application using [WASM binding](./cedarling-wasm.md). -While this documentation is in progress, you can ask questions through [GitHub Discussions](https://github.com/JanssenProject/jans/discussions) or the [community chat on Gitter](https://gitter.im/JanssenProject/Lobby). Any questions you have will help determine what information our documentation should cover. +## Mobile apps -## Want to contribute? +Cedarling provides [UniFFI interface binding](./uniffi/cedarling-uniffi.md) to integrate with mobile applications running on [Android](./uniffi/cedarling-android.md) +or [iOS](./cedarling-ios.md). + +## Server side applications + +Applications running on server can leverage +Cedarling [sidecar](./cedarling-sidecar.md) to integrate Cedarling. For instance, +a [load balancer](./cedarling-krakend.md) can run sidecar container and use it +to perform server-side authorization checks. -If you have content you'd like to contribute to this page in the meantime, you can get started with our [Contribution guide](https://docs.jans.io/head/CONTRIBUTING/). \ No newline at end of file diff --git a/docs/cedarling/cedarling-quick-start.md b/docs/cedarling/cedarling-quick-start.md index 95e6f96a398..869cfb728c6 100644 --- a/docs/cedarling/cedarling-quick-start.md +++ b/docs/cedarling/cedarling-quick-start.md @@ -1,19 +1,416 @@ --- tags: - - cedarling - - quick start guide + - administration + - Cedar + - Cedarling + - Quick start guide + - Cedarling Hello World --- -# Getting Started with Cedarding +# Cedarling Quick Start Guide -## This content is in progress +## Introduction -The Janssen Project documentation is currently in development. Topic pages are being created in order of broadest relevance, and this page is coming in the near future. +Cedarling is an authorization decision service that allows fine-grained access control using policies. +In this guide, we'll demonstrate how to use Cedarling as a sidecar for an API Gateway to authorize requests. +This setup involves configuring the Cedarling sidecar to evaluate policies and authorizing requests to a +protected resource based on those policies. -## Have questions in the meantime? +### Sequence diagram -While this documentation is in progress, you can ask questions through [GitHub Discussions](https://github.com/JanssenProject/jans/discussions) or the [community chat on Gitter](https://gitter.im/JanssenProject/Lobby). Any questions you have will help determine what information our documentation should cover. +```mermaid +sequenceDiagram +title API Gateway +actor User +participant Gateway +participant Sidecar -## Want to contribute? +User->Gateway: GET /protected\nAuthorization: Bearer ... +Gateway->Sidecar: POST /cedarling/evaluation\n{"subject": {"type": "JWT", "id": "cedarling", "properties": {"access_token": "..."} }} +Sidecar->Sidecar: cedarling.authorize(access_token) -If you have content you'd like to contribute to this page in the meantime, you can get started with our [Contribution guide](https://docs.jans.io/head/CONTRIBUTING/). \ No newline at end of file +alt ALLOW + Sidecar->Gateway: {"decision": true} + Gateway->User: 200 {"result": "protected resource"} +else DENY + Sidecar->Gateway: {"decision": false, "context": {...}} + Gateway->User: 403 Forbidden +end + +``` + +### Sample Authzen request + +``` +{ + "subject": { + "type": "token_bundle", + "id": "some_id", + "properties": { + "access_token": "" + } + }, + "resource": { + "type": "Jans::HTTP_Request", + "id": "some_id", + "properties": { + "header": {}, + "url": { + "protocol": "http", + "host": "www.acme.tld", + "path": "/protected" + } + } + }, + "action": { + "name": "Jans::Action::\"GET\"" + }, + "context": {} +} + +``` + +## Prerequisites + +Before you begin, make sure you have the following: + +* `Docker` installed on your machine +* `Python 3.10` or higher +* `pipx` and `Poetry` installed if you're not using Docker + +## Policy Store Setup (Agama Lab) + +To begin using Cedarling, you need to set up a policy store. We’ll use this [Agama Lab](https://cloud.gluu.org/agama-lab/login) for this purpose. + +1. Sign in to [Agama Lab](https://cloud.gluu.org/agama-lab/login) using your GitHub account and click on Policy Designer. + ![image](../assets/cedarling-policy-designer.png) +2. Choose a repository to store your Cedarling policies and schemas. Ensure that the repository has at least one commit on the default branch. + ![image](../assets/cedarling-select-repo.png) +3. After initialization, create a policy store named `gatewayDemo`. This will be your Cedar namespace. + ![image](../assets/cedarling-policy-store-name.png) +4. Open the policy store and navigate to Policies. +5. Click `Add Policy`, select `Text Editor`. + ![image](../assets/cedarling-add-policy.png) +6. Paste the following Cedar policy: + ```bash + @id("allow_one") + permit( + principal is gatewayDemo::Workload, + action == gatewayDemo::Action::"GET", + resource is gatewayDemo::HTTP_Request + ) + when { + principal has access_token.scope && + principal.access_token.scope.contains("profile") + }; + ``` +7. Click `Save`. Agama Lab will validate your policy. +8. Next, click on `Trusted Issuers` and add the following issuer: + + * Name: `Gluu` + * Description: `Gluu` + * OpenID Configuration Endpoint: `https://account.gluu.org/.well-known/openid-configuration` + * Copy the URL for your policy store; you'll need it for the sidecar setup. + ![image](../assets/cedarling-copylink.png) + +## Deploy Cedarling Sidecar + +### Docker Instructions + +Create a file named `bootstrap.json`. You may use the [sample](https://github.com/JanssenProject/jans/blob/main/jans-cedarling/flask-sidecar/secrets/bootstrap.json) file. + +* Set `CEDARLING_POLICY_STORE_URI` to the URL you copied from Agama Lab. +* Set `CEDARLING_USER_AUTHZ` to "disabled" +* Set `CEDARLING_TOKEN_CONFIGS` to the following value: + +```json + { + "access_token": { + "entity_type_name": "gatewayDemo::Access_token", + "iss": "disabled", + "aud": "disabled", + "sub": "disabled", + "nbf": "disabled", + "exp": "disabled", + "jti": "disabled" + }, + "id_token": { + "entity_type_name": "gatewayDemo::id_token", + "iss": "disabled", + "aud": "disabled", + "sub": "disabled", + "nbf": "disabled", + "exp": "disabled", + "jti": "disabled" + }, + "userinfo_token": { + "entity_type_name": "gatewayDemo::Userinfo_token", + "iss": "disabled", + "aud": "disabled", + "sub": "disabled", + "nbf": "disabled", + "exp": "disabled", + "jti": "disabled" + } +} +``` + + * Set `CEDARLING_MAPPING_WORKLOAD` to gatewayDemo::Workload + + * Set `CEDARLING_ID_TOKEN_TRUST_MODE` to "none" + + Pull the Docker image: + + ```bash + docker pull ghcr.io/janssenproject/jans/cedarling-flask-sidecar:0.0.0-nightly + ``` + + Run the Docker image, replacing `` with the absolute path to your bootstrap file: + +```bash +docker run -e APP_MODE='development' -e CEDARLING_BOOTSTRAP_CONFIG_FILE=/bootstrap.json -e SIDECAR_DEBUG_RESPONSE=True --mount type=bind,src=,dst=/bootstrap.json -p 5000:5000 -d ghcr.io/janssenproject/jans/cedarling-flask-sidecar:0.0.0-nightly +``` + +The sidecar is now running on [http://127.0.0.1:5000](http://127.0.0.1:5000). Keep track of the output of the previous command, +it is your Docker container ID. + +### Python instructions (if Docker is unavailable) + +* Clone the Janssen repository and navigate to `jans/jans-cedarling/flask-sidecar`. +* Run `poetry install` to install dependencies. +* Download and install the latest Cedarling nightly wheel: +```bash +wget https://github.com/JanssenProject/jans/releases/download/nightly/cedarling_python-0.0.0-cp310-cp310-manylinux_2_31_x86_64.whl +``` +* Install the nightly wheel: + +``` +poetry run pip install cedarling_python-0.0.0-cp310-cp310-manylinux_2_31_x86_64.whl +``` +* Modify `secrets/bootstrap.json` to your specifications. + +* Navigate to `jans/jans-cedarling/flask-sidecar/main` + +* Create a file called `.env` and paste in the following content. Alternatively, set the following environment variables: + +``` +APP_MODE=development +CEDARLING_BOOTSTRAP_CONFIG_FILE=../secrets/bootstrap.json +SIDECAR_DEBUG_RESPONSE=False +``` +* Run the sidecar: poetry run `flask run` + +* The sidecar is now running on [http://127.0.0.1:5000](http://127.0.0.1:5000) + +## Setup Test Gateway + +We will use Flask to create a simple API Gateway. + +* Create a folder called `demo` and navigate to it. +* Create a virtual environment and activate it: + + ```bash + python -m venv venv + source venv/bin/activate + ``` + +* Install Flask and requests. + +```bash +pip install flask requests + +``` + +* Create a file called `gateway.py` with the following content: + + +```python +from flask import Flask, abort, request +import requests + +app = Flask(__name__) + +@app.route("/protected") +def protected(): + token = request.headers.get("Authorization") + if token is None: + abort(403) + token_jwt = token.split(" ")[1] + payload = { + "subject": { + "type": "token_bundle", + "id": "some_id", + "properties": { + "access_token": token_jwt + } + }, + "resource": { + "type": "gatewayDemo::HTTP_Request", + "id": "some_id", + "properties": { + "header": {}, + "url": { + "protocol": "http", + "host": "www.acme.tld", + "path": "/protected" + } + } + }, + "action": { + "name": "gatewayDemo::Action::\"GET\"" + }, + "context": {} + } + response = requests.post("http://127.0.0.1:5000/cedarling/evaluation", json=payload) + if response.ok and response.json()["decision"] == True: + return {"protected_content": "secret"} + abort(403) + +if __name__ == '__main__': + app.run(port=5001) + +``` + +* Run the gateway: + +```bash +flask --app gateway run --port 5001 +``` + +## Test the Setup + +* Access the protected endpoint via browser: [http://127.0.0.1:5001/protected](http://127.0.0.1:5001/protected). +You should get a 403 Forbidden response. + +* Access the protected endpoint via curl with the provided JWT: + +```bash +curl http://127.0.0.1:5001/protected -H "Authorization: Bearer eyJraWQiOiJjb25uZWN0X2Y5YTAwN2EyLTZkMGItNDkyYS05MGNkLWYwYzliMWMyYjVkYl9zaWdfcnMyNTYiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJxenhuMVNjcmI5bFd0R3hWZWRNQ2t5LVFsX0lMc3BaYVFBNmZ5dVlrdHcwIiwiY29kZSI6IjNlMmEyMDEyLTA5OWMtNDY0Zi04OTBiLTQ0ODE2MGMyYWIyNSIsImlzcyI6Imh0dHBzOi8vYWNjb3VudC5nbHV1Lm9yZyIsInRva2VuX3R5cGUiOiJCZWFyZXIiLCJjbGllbnRfaWQiOiJkN2Y3MWJlYS1jMzhkLTRjYWYtYTFiYS1lNDNjNzRhMTFhNjIiLCJhdWQiOiJkN2Y3MWJlYS1jMzhkLTRjYWYtYTFiYS1lNDNjNzRhMTFhNjIiLCJhY3IiOiJzaW1wbGVfcGFzc3dvcmRfYXV0aCIsIng1dCNTMjU2IjoiIiwibmJmIjoxNzMxOTUzMDMwLCJzY29wZSI6WyJyb2xlIiwib3BlbmlkIiwicHJvZmlsZSIsImVtYWlsIl0sImF1dGhfdGltZSI6MTczMTk1MzAyNywiZXhwIjoxNzMyMTIxNDYwLCJpYXQiOjE3MzE5NTMwMzAsImp0aSI6InVaVWgxaERVUW82UEZrQlBud3BHemciLCJ1c2VybmFtZSI6IkRlZmF1bHQgQWRtaW4gVXNlciIsInN0YXR1cyI6eyJzdGF0dXNfbGlzdCI6eyJpZHgiOjMwNiwidXJpIjoiaHR0cHM6Ly9qYW5zLnRlc3QvamFucy1hdXRoL3Jlc3R2MS9zdGF0dXNfbGlzdCJ9fX0.Pt-Y7F-hfde_WP7ZYwyvvSS11rKYQWGZXTzjH_aJKC5VPxzOjAXqI3Igr6gJLsP1aOd9WJvOPchflZYArctopXMWClbX_TxpmADqyCMsz78r4P450TaMKj-WKEa9cL5KtgnFa0fmhZ1ZWolkDTQ_M00Xr4EIvv4zf-92Wu5fOrdjmsIGFot0jt-12WxQlJFfs5qVZ9P-cDjxvQSrO1wbyKfHQ_txkl1GDATXsw5SIpC5wct92vjAVm5CJNuv_PE8dHAY-KfPTxOuDYBuWI5uA2Yjd1WUFyicbJgcmYzUSVt03xZ0kQX9dxKExwU2YnpDorfwebaAPO7G114Bkw208g" +``` + +* If the JWT is valid and the policy allows access, you should receive the following response: + +```json +{ + "protected_content": "secret" +} +``` + +## Check Logs + +The cedarling decision log will be outputted by the Docker container or directly by the API to stdout. In the case of Docker, this can be retrieved like so: + +```bash +$ docker logs +``` +```json +{ + "request_id": "0194cdbc-b8c7-798d-8cc8-fb483448e6fa", + "timestamp": "2025-02-03T21:34:44.935Z", + "log_kind": "Decision", + "pdp_id": "e122cc37-14f7-4033-a547-6791f339218b", + "policystore_id": "c92b24bb010b772e7702811ae0725986bf7d3b39656e", + "policystore_version": "1.6.15", + "principal": "Workload", + "Workload": {"client_id": "slkacm3cv5-vat1u~elog"}, + "diagnostics": { + "reason": ["840da5d85403f35ea76519ed1a18a33989f855bf1cf8"], + "errors": [] + }, + "action": "gatewayDemo::Action::\"GET\"", + "resource": "gatewayDemo::HTTP_Request::\"some_id\"", + "decision": "ALLOW", + "tokens": { + "access_token": { + "jti": "uZUh1hDUQo6PFkBPnwpGzg" + } + }, + "decision_time_ms": 0 +} +``` + + +## Customizing the policy + +Let's add one more check in the policy. This time we want to check if the `acr` +in the access token matches a particular value, for example `simple_password_auth`. +This change will essentially involve two changes. + +1. Update the schema +2. Update the policy + +Let's update the schema first using steps the below: + +1. Go to the `Policy Designer`. +2. Navigate to `Schema` → `Entity Types`. +3. Edit the `access_token` entity type. +4. Add a new field `acr` with the type set to `String`. +5. Save the schema. + +Once the schema has been updated, your new updated Access_token entity type +json should be similar to the one below: + +```json +{ + "shape": { + "type": "Record", + "attributes": { + "aud": { + "type": "EntityOrCommon", + "name": "String" + }, + "exp": { + "type": "EntityOrCommon", + "name": "Long" + }, + "iat": { + "type": "EntityOrCommon", + "name": "Long" + }, + "iss": { + "type": "EntityOrCommon", + "name": "TrustedIssuer" + }, + "jti": { + "type": "EntityOrCommon", + "required": false, + "name": "String" + }, + "nbf": { + "type": "EntityOrCommon", + "required": false, + "name": "Long" + }, + "scope": { + "type": "Set", + "required": false, + "element": { + "type": "EntityOrCommon", + "name": "String" + } + }, + "acr": { + "type": "String", + "required": false + } + } + } +} +``` + +Let's make the corresponding changes in the policy. + +``` +@id("allow_one") +permit( + principal is gatewayDemo::Workload, + action == gatewayDemo::Action::"GET", + resource is gatewayDemo::HTTP_Request +) +when { + principal has access_token.acr && + principal.acr == "simple_password_auth" +}; +``` + +The policy now checks whether the `acr` value in the access token is present and matches `simple_password_auth`.