Skip to main content

CerbosのAPI

Cerbosは、アプリケーションからのアクセス制御リクエストを処理するためのAPIを提供しています。ここでは、CerbosのAPIの使用方法と様々な言語での統合について説明します。

APIの概要 #

Cerbosは、以下の2つのインターフェースを提供しています:

  1. gRPC API - 高性能なバイナリプロトコルを使用したAPI(ポート3593)
  2. HTTP API - RESTful APIとしてgRPC APIをラップしたもの(ポート3592)

主要なAPIエンドポイント #

リソースのチェック(Check Resources) #

複数のリソースに対する複数のアクションのアクセス許可を一度にチェックします。

HTTP API:

POST /api/check/resources

リクエスト例:

{
  "requestId": "test01",
  "principal": {
    "id": "john",
    "roles": ["user"],
    "attr": {
      "department": "marketing",
      "region": "europe"
    }
  },
  "resources": [
    {
      "resource": {
        "kind": "document:object",
        "id": "doc123",
        "attr": {
          "owner": "john",
          "status": "published",
          "department": "marketing"
        }
      },
      "actions": ["view", "edit", "delete"]
    },
    {
      "resource": {
        "kind": "document:object",
        "id": "doc456",
        "attr": {
          "owner": "jane",
          "status": "published",
          "department": "engineering"
        }
      },
      "actions": ["view", "edit", "delete"]
    }
  ]
}

レスポンス例:

{
  "requestId": "test01",
  "results": [
    {
      "resource": {
        "kind": "document:object",
        "id": "doc123"
      },
      "actions": {
        "view": "EFFECT_ALLOW",
        "edit": "EFFECT_ALLOW",
        "delete": "EFFECT_ALLOW"
      }
    },
    {
      "resource": {
        "kind": "document:object",
        "id": "doc456"
      },
      "actions": {
        "view": "EFFECT_ALLOW",
        "edit": "EFFECT_DENY",
        "delete": "EFFECT_DENY"
      }
    }
  ]
}

単一リソースのチェック(Check Resource) #

単一のリソースに対する複数のアクションのアクセス許可をチェックします。

HTTP API:

POST /api/check/resource

リクエスト例:

{
  "requestId": "test02",
  "principal": {
    "id": "john",
    "roles": ["user"],
    "attr": {
      "department": "marketing",
      "region": "europe"
    }
  },
  "resource": {
    "kind": "document:object",
    "id": "doc123",
    "attr": {
      "owner": "john",
      "status": "published",
      "department": "marketing"
    }
  },
  "actions": ["view", "edit", "delete"]
}

レスポンス例:

{
  "requestId": "test02",
  "results": {
    "view": "EFFECT_ALLOW",
    "edit": "EFFECT_ALLOW",
    "delete": "EFFECT_ALLOW"
  }
}

プランの作成(Plan Resources) #

特定の条件を満たすリソースを検索するためのクエリプランを作成します。

HTTP API:

POST /api/plan/resources

リクエスト例:

{
  "requestId": "test03",
  "principal": {
    "id": "john",
    "roles": ["user"],
    "attr": {
      "department": "marketing",
      "region": "europe"
    }
  },
  "resource": {
    "kind": "document:object"
  },
  "action": "view"
}

レスポンス例:

{
  "requestId": "test03",
  "filter": {
    "kind": "KIND_CONDITIONAL",
    "condition": "request.resource.attr.status == \"published\" || request.resource.attr.owner == \"john\""
  }
}

言語別のSDK #

Cerbosは、様々な言語でのSDKを提供しています。以下に、主要な言語でのCerbos統合例を示します。

Go #

package main

import (
	"context"
	"log"

	"github.com/cerbos/cerbos-sdk-go/cerbos"
)

func main() {
	// クライアントの作成
	c, err := cerbos.New("localhost:3593", cerbos.WithPlaintext())
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	// プリンシパルの定義
	principal := cerbos.NewPrincipal("john", "user")
	principal.WithAttr("department", "marketing")
	principal.WithAttr("region", "europe")

	// リソースの定義
	resource := cerbos.NewResource("document:object", "doc123")
	resource.WithAttributes(map[string]any{
		"owner":      "john",
		"status":     "published",
		"department": "marketing",
	})

	// アクセスチェック
	actions := []string{"view", "edit", "delete"}
	resp, err := c.CheckResource(context.Background(), principal, resource, actions)
	if err != nil {
		log.Fatalf("Failed to check resource: %v", err)
	}

	// 結果の処理
	for _, action := range actions {
		allowed := resp.IsAllowed(action)
		log.Printf("Action %s is allowed: %v", action, allowed)
	}
}

Node.js #

const { GRPC: Cerbos } = require("@cerbos/grpc");

async function main() {
  // クライアントの作成
  const cerbos = new Cerbos("localhost:3593", { tls: false });

  // リクエストの作成
  const request = {
    principal: {
      id: "john",
      roles: ["user"],
      attributes: {
        department: "marketing",
        region: "europe",
      },
    },
    resource: {
      kind: "document:object",
      id: "doc123",
      attributes: {
        owner: "john",
        status: "published",
        department: "marketing",
      },
    },
    actions: ["view", "edit", "delete"],
  };

  // アクセスチェック
  try {
    const decision = await cerbos.checkResource(request);
    
    // 結果の処理
    for (const action of request.actions) {
      console.log(`Action ${action} is allowed: ${decision.isAllowed(action)}`);
    }
  } catch (error) {
    console.error("Failed to check resource:", error);
  }
}

main();

Python #

from cerbos.sdk.client import CerbosClient
from cerbos.sdk.model import Principal, Resource

def main():
    # クライアントの作成
    client = CerbosClient("localhost:3593", tls=False)
    
    # プリンシパルの定義
    principal = Principal(
        "john",
        roles=["user"],
        attributes={
            "department": "marketing",
            "region": "europe"
        }
    )
    
    # リソースの定義
    resource = Resource(
        "document:object",
        "doc123",
        attributes={
            "owner": "john",
            "status": "published",
            "department": "marketing"
        }
    )
    
    # アクセスチェック
    actions = ["view", "edit", "delete"]
    decision = client.check_resource(principal, resource, actions)
    
    # 結果の処理
    for action in actions:
        print(f"Action {action} is allowed: {decision.is_allowed(action)}")

if __name__ == "__main__":
    main()

Java #

import dev.cerbos.sdk.CerbosBlockingClient;
import dev.cerbos.sdk.CerbosClientBuilder;
import dev.cerbos.sdk.CheckResult;
import dev.cerbos.sdk.builders.Principal;
import dev.cerbos.sdk.builders.Resource;

import static dev.cerbos.sdk.builders.AttributeValue.boolValue;
import static dev.cerbos.sdk.builders.AttributeValue.stringValue;

import java.util.Map;

public class App {
    public static void main(String[] args) throws Exception {
        // クライアントの作成
        CerbosBlockingClient client = new CerbosClientBuilder("localhost:3593")
            .withPlaintext()
            .buildBlockingClient();
        
        // プリンシパルの定義
        Principal principal = Principal.newInstance("john", "user")
            .withAttribute("department", stringValue("marketing"))
            .withAttribute("region", stringValue("europe"));
        
        // リソースの定義
        Resource resource = Resource.newInstance("document:object", "doc123")
            .withAttributes(
                Map.of(
                    "owner", stringValue("john"),
                    "status", stringValue("published"),
                    "department", stringValue("marketing")
                )
            );
        
        // アクセスチェック
        String[] actions = {"view", "edit", "delete"};
        CheckResult result = client.checkResource(principal, resource, actions);
        
        // 結果の処理
        for (String action : actions) {
            boolean allowed = result.isAllowed(action);
            System.out.printf("Action %s is allowed: %b%n", action, allowed);
        }
    }
}

.NET #

using Cerbos.Api.V1.Effect;
using Cerbos.Sdk.Builder;
using Cerbos.Sdk.Response;

class Program
{
    static void Main(string[] args)
    {
        // クライアントの作成
        var client = CerbosClientBuilder.ForTarget("localhost:3593")
            .WithPlaintext()
            .Build();
        
        // リクエストの作成
        var request = CheckResourceRequest
            .NewInstance()
            .WithPrincipal(
                Principal
                    .NewInstance("john", "user")
                    .WithAttribute("department", AttributeValue.StringValue("marketing"))
                    .WithAttribute("region", AttributeValue.StringValue("europe"))
            )
            .WithResource(
                Resource
                    .NewInstance("document:object", "doc123")
                    .WithAttribute("owner", AttributeValue.StringValue("john"))
                    .WithAttribute("status", AttributeValue.StringValue("published"))
                    .WithAttribute("department", AttributeValue.StringValue("marketing"))
            )
            .WithActions("view", "edit", "delete");
        
        // アクセスチェック
        CheckResourceResponse result = client.CheckResource(request);
        
        // 結果の処理
        foreach (var action in new[] { "view", "edit", "delete" })
        {
            bool allowed = result.IsAllowed(action);
            Console.WriteLine($"Action {action} is allowed: {allowed}");
        }
    }
}

認証統合 #

Cerbosは、様々な認証プロバイダーと統合できます。以下に、JWT(JSON Web Token)を使用した統合例を示します。

JWT統合 #

JWTからプリンシパル情報を抽出し、Cerbosに渡すことができます。

const { GRPC: Cerbos } = require("@cerbos/grpc");
const jwt = require("jsonwebtoken");

async function checkAccess(token, resourceKind, resourceId, resourceAttr, actions) {
  // JWTの検証と解析
  const decoded = jwt.verify(token, process.env.JWT_SECRET);
  
  // プリンシパル情報の抽出
  const principal = {
    id: decoded.sub,
    roles: decoded.roles || [],
    attributes: decoded.attributes || {},
  };
  
  // Cerbosクライアントの作成
  const cerbos = new Cerbos("localhost:3593", { tls: false });
  
  // アクセスチェック
  const decision = await cerbos.checkResource({
    principal,
    resource: {
      kind: resourceKind,
      id: resourceId,
      attributes: resourceAttr,
    },
    actions,
  });
  
  return decision;
}

管理API #

Cerbosは、ポリシーの管理や監視のための管理APIも提供しています。

ポリシーのリスト取得 #

HTTP API:

GET /admin/policies

ポリシーの追加 #

HTTP API:

POST /admin/policies

ポリシーの削除 #

HTTP API:

DELETE /admin/policies/{id}

ヘルスチェック #

HTTP API:

GET /health

まとめ #

CerbosのAPIを使用することで、アプリケーションに柔軟で強力なアクセス制御機能を簡単に統合できます。様々な言語のSDKが提供されており、開発者は自分の好みの言語でCerbosを利用できます。また、JWTなどの認証プロバイダーとの統合も容易です。

[出典: https://docs.cerbos.dev/cerbos/latest/api/]