0.0.8 • Published 9 months ago

@estino/cerbos-ts-codegen v0.0.8

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

@estino/cerbos-ts-codegen

Create typescript types based on cerbos schemas.

Currently cerbos does not provide a way to generate typescript types based on the schemas, see https://github.com/cerbos/cerbos-sdk-javascript/issues/540. This project aims to fill that gap for our needs for now.

Usage

npx @estino/cerbos-ts-codegen@latest

Approach taken

  • parses the provided cerbos resource policies provided in yaml files
  • parses the provided schema files
  • creates a TypeScript Declaration File (.d.ts) merging the builtin declarations to enforce stricter parameter types for the isAllowed method of @cerbos/http

Known limitations

  • many! Among others:
  • multiple schemas with the same file name in different folders are not supported
  • fetching schemas and policies from the Admin API is not yet supported, though the CLI already hints at it
  • only the isAllowed method of @cerbos/http is supported right now
  • derived roles are not supported as we don't use them currently
  • opting out of schemas via ignoreWhen is not supported as we don't use it currently
  • I am not sure yet what will happen in more advanced use cases, as we haven't used them yet. Such as using common schema fragments, schema titles etc.

Example

Input Resource Policy & Schemas

# policies/contract.yaml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  version: default
  resource: contract

  rules:
    - actions:
        - "view"
      effect: EFFECT_ALLOW
      roles: [user]
      condition:
        match:
          expr: P.attr.department == "legal"
    - actions:
        - "edit"
      effect: EFFECT_ALLOW
      roles: [user]
      condition:
        match:
          all:
            of:
              - expr: P.attr.organisation == R.attr.organisation
              - expr: P.attr.department == "legal"

  schemas:
    principalSchema:
      ref: cerbos://schemas/contract-principal.json
    resourceSchema:
      ref: cerbos://schemas/contract.json
# schemas/contract-principal.json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties":
    {
      "department": { "enum": ["tech", "legal"] },
      "organisation": { "type": "string" },
    },
  "required": ["department", "organisation"],
}
# schemas/contract.json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": { "organisation": { "type": "string" } },
  "required": ["organisation"],
}

Codegen Result

import type {
	Principal,
	IsAllowedRequest,
} from "@cerbos/core/lib/types/external"

declare module "@cerbos/http" {
	interface HTTP {
		isAllowed(request: isAllowedParams): Promise<boolean>
	}
	export interface ContractPrincipal {
		department: "tech" | "legal"
		organisation: string
		[k: string]: unknown
	}
	export interface Contract {
		organisation: string
		[k: string]: unknown
	}

	type isAllowedParamsContract = {
		principal: Principal & {
			attributes?: ContractPrincipal
		}
		resource: { kind: "contract"; attributes: Contract }
		action: "view" | "edit"
	}
	type isAllowedParams = IsAllowedRequest & isAllowedParamsContract
}