Skip to content

Protect Config API using Cedarling

Kiran Mali edited this page Oct 9, 2025 · 7 revisions

Currently, Config-API is using the OAuth scope to protect the endpoint. In this new approach, we are going to provide Cedarling authz. The user can switch between OAuth and Cedarling protection. The idea is coming from the protection of Frontend(Admin-UI) and Backend(Config-API) using Cedarling.

graph LR
    %% Style definitions
    classDef green fill:#d5f0d5,stroke:#000,stroke-width:1px;
    classDef yellow fill:#fff2cc,stroke:#000,stroke-width:1px;
    classDef blue fill:#d9e8fb,stroke:#000,stroke-width:1px;
    classDef orange fill:#f9d5b3,stroke:#000,stroke-width:1px;

    %% Top level actors
    AUI -.->|Access APIs| CAB
    U["👥 Users"] -.->|Access components| AUI
    AD["👤 Admin"] -.->|Enable cedarling<br/>Add Policy store URL| CCP
    AD -.->|Manage policy store<br/>edit/delete schema| PA

    %% Admin UI Frontend
    subgraph AUI[Admin UI Frontend]
        CCP[Cedarling Config Page]
        CC[Cedarling Client<br/>- authz user request]
    end
    class AUI green

    %% Config API Backend
    subgraph CAB[Config API Backend]
        CCB[Cedarling Client<br/>- authz user request]
    end
    class CAB yellow

    %% Policy Authoring
    subgraph PA[Policy Authoring]
        ALPD[🧩 Agama Lab Policy Designer]
        GHR[💾 GitHub Repository]
        ALPD -.-> GHR
    end
    class PA blue

    %% Lock
    L["🔒 Lock"]
    class L orange

    %% Connections between UI & Backend
    CC -.->|Send Audit data| L
    CCB -.->|Send Audit Data| L

    %% Policy store fetch
    CCB -.->|Fetch policy store| GHR
    CC -.->|Fetch policy store| GHR
Loading

API and DB Configuration Properties

Properties that we need to configure Cedarling. We need to make/update the API and save properties in the DB.

  • policy_store_url: String, used to store GitHub policy store URL for Config-API.
  • is_local_policy_store_on: Boolean, if true, Config-API will use policy_store_local to fetch policies. If false, use policy_store_url to fetch policies from GitHub. It is good for production security reasons.
  • policy_store_local: JSON, used to store the config API policy store JSON.

For Admin-UI, we need some more properties.

  • admin_ui_policy_store_local: used to store admin ui policy store JSON.
  • admin_ui_policy_store_url: used to store GitHub policy store URL for Admin-UI.
  • is_active: if true, then enable cedarling authz for Admin-UI, otherwise no cedarling authz.

Policy Store

https://github.com/kdhttps/admin-ui-cedarling-config/blob/agama-lab-policy-designer/84c511a8d416187492bf7af0501282952347214dc5a6.json

Principals

  • Workload(access_token, client_id, iss, name, rp_id, spiffe_id)

Resources

Resources take fron Config API endpoints. Check swagger here.

  1. HTTP_Request::"/jans-config-api/api/v1/acrs"
  2. HTTP_Request::"/jans-config-api/api/v1/attributes"
  3. HTTP_Request::"/jans-config-api/api/v1/config/cache"

more...

Action

  • POST
  • PUT
  • DELETE
  • PATCH
  • GET

Policies

Scope based authz policies

@AcrsRead
permit(
  principal is Jans::Workload,
  action in [Jans::Action::"GET"],
  resource == Jans::HTTP_Request::"/jans-config-api/api/v1/acrs"
)
when {
  principal has access_token.scope &&
  principal.access_token.scope.containsAny(["https://jans.io/oauth/config/acrs.readonly","https://jans.io/oauth/config/acrs.write","https://jans.io/oauth/config/read-all"])
};
@AcrsUpdate
permit(
  principal is Jans::Workload,
  action in [Jans::Action::"PUT"],
  resource == Jans::HTTP_Request::"/jans-config-api/api/v1/acrs"
)
when {
  principal has access_token.scope &&
  principal.access_token.scope.containsAny(["https://jans.io/oauth/config/acrs.write","https://jans.io/oauth/config/write-all"])
};
@AttributeGet
permit(
  principal is Jans::Workload,
  action in [Jans::Action::"GET"],
  resource == Jans::HTTP_Request::"/jans-config-api/api/v1/attributes"
)
when {
  principal has access_token.scope &&
  principal.access_token.scope.containsAny(["https://jans.io/oauth/config/attributes.readonly","https://jans.io/oauth/config/attributes.write", "https://jans.io/oauth/config/read-all"])
};
@AttributeUpdate
permit(
  principal is Jans::Workload,
  action in [Jans::Action::"POST", Jans::Action::"PUT", Jans::Action::"PATCH"],
  resource == Jans::HTTP_Request::"/jans-config-api/api/v1/attributes"
)
when {
  principal has access_token.scope &&
  principal.access_token.scope.containsAny(["https://jans.io/oauth/config/attributes.write","https://jans.io/oauth/config/write-all"])
};

More...

Clone this wiki locally