What is the best practice for debugging? I'm tryi...
# help
m
What is the best practice for debugging? I'm trying to figure out why this specific code returns forbidden. But I cannot figure out where my problem is, and I don't know where to look.
Copy code
export const runtime = 'nodejs';

import { NextRequest, NextResponse } from 'next/server';
import { can } from '@/lib/cerbos';

export async function GET(_req: NextRequest, { params }: { params: Promise<{ id: string }> }): Promise<NextResponse> {
  const { id: docId } = await params;

  const principal = { id: 'user123', roles: ['reader'] };

  try {
    const allowed = await can(principal, 'view', {
      kind: 'document',
      id: docId,
    });

    if (!allowed) {
      return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
    }

    return NextResponse.json({ id: docId, content: 'This is secret.' });
  } catch (err) {
    console.error('Cerbos unreachable:', err);
    return NextResponse.json({ error: 'Authorization service unavailable' }, { status: 503 });
  }
}
Copy code
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  version: default
  resource: document
  rules:
    - actions: ['view']
      roles: ['reader']
      effect: EFFECT_ALLOW
Also, are there a way to see what policies that Cerbos is currently evaluating against? I've set everything up with docker compose, and I'm not 100% that it is setup correctly.
// lib/cerbos.ts
Copy code
import { GRPC } from '@cerbos/grpc';

const host = process.env.CERBOS_HOST ?? 'cerbos';
const port = process.env.CERBOS_GRPC_PORT ?? '3593';

export const cerbos = new GRPC(`${host}:${port}`, { tls: false });

export async function can(principal: { id: string; roles: string[] }, action: string, resource: { kind: string; id: string }): Promise<boolean> {
  return cerbos.isAllowed({
    principal: { id: principal.id, roles: principal.roles },
    resource: { kind: resource.kind, id: resource.id },
    action,
  });
}
o
Hi @Martin Carlsson, I have created a playground instance consisting of your policy and an example
(principal, resource, action)
. The policy seems to be fine and it is working as expected. (pg) Could you send a request via cURL to Cerbos instance running in docker?
Copy code
curl -X POST '127.0.0.1:3592/api/check/resources' \
--header 'Content-Type: application/json' \
--data-raw '{
  "requestId": "123123",
  "principal": {
    "id": "user123",
    "roles": [
      "reader"
    ],
    "attr": {}
  },
  "resources": [
    {
      "resource": {
        "kind": "document",
        "id": "docId",
        "attr": {}
      },
      "actions": [
        "view"
      ]
    }
  ]
}'
m
I got a little further, so now my service is approving the request, and I got a response from your curl command.
o
This could be a configuration problem. Could you share the cerbos configuration file, and also the
docker-compose
file? Also when cerbos PDP launches, it states where it read the cerbos configuration file as:
Copy code
{
  "log.level": "info",
  "@timestamp": "2025-04-19T12:31:32.141Z",
  "log.logger": "cerbos.server",
  "message": "Loading configuration from __default__"
}
If it is
__default__
like it is reported above, it means it uses the default configuration file embedded with the cerbos image. Could you check if this is the case?
m
Thanks @oguzhan I actually think it is working now. I am able to get the expected result in my API.
My development setup _(I'm using devcontainers)_: Again .. it is working locally. But if you have any improvements, it is highly appreciated.
.devcontainer/devcontainer.json
Copy code
{
  "name": "PowerBI",
  "dockerComposeFile": [
    "docker-compose.yml"
  ],
  "service": "app",
  "runServices": [
    "app",
    "cerbos"
  ],
  "shutdownAction": "stopCompose",
  "workspaceFolder": "/workspace",
  "postCreateCommand": "zsh .devcontainer/postCreateCommand.zsh",
  "forwardPorts": [
    3000,
    3593
  ],
  "features": {
    "<http://ghcr.io/devcontainers/features/azure-cli:1|ghcr.io/devcontainers/features/azure-cli:1>": {
      "version": "latest",
      "bicepVersion": "latest"
    },
    "<http://ghcr.io/devcontainers/features/common-utils:2|ghcr.io/devcontainers/features/common-utils:2>": {
      "installZsh": true,
      "configureZshAsDefaultShell": true,
      "installOhMyZsh": true,
      "installOhMyZshConfig": true,
      "upgradePackages": true
    }
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "bradlc.vscode-tailwindcss",
        "vincaslt.highlight-matching-tag",
        "formulahendry.auto-rename-tag",
        "ms-vscode.vscode-typescript-next",
        "mtxr.sqltools-driver-pg"
      ]
    }
  },
  "remoteUser": "root"
}
.devcontainer/docker-compose.yml
Copy code
services:
  app:
    image: <http://mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm|mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm>
    command: sleep infinity
    volumes:
      - ../:/workspace:cached
      - /var/run/docker.sock:/var/run/docker.sock
    working_dir: /workspace
    depends_on:
      - cerbos
    environment:
      - GRPC_DNS_RESOLVER=native
      - CERBOS_HOST=cerbos
      - CERBOS_GRPC_PORT=3593

  cerbos:
    container_name: cerbos
    image: <http://ghcr.io/cerbos/cerbos:latest|ghcr.io/cerbos/cerbos:latest>
    command:
      - server
      - --config
      - /workspace/cerbos/cerbos.yaml
    volumes:
      - ../cerbos:/workspace/cerbos:ro
    ports:
      - '3593:3593'
      - '3592:3592'
cerbos/cerbos.yaml
Copy code
server:
  grpcListenAddr: ':3593'

storage:
  driver: disk
  disk:
    directory: /workspace/cerbos/policies