0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenPolicyAgent入門とGoでの利用

Posted at

Open Policy Agentについて

Open Policy Agentとは、オープンソースのポリシーエンジンです。CNCFのGraduatedプロジェクトとして登録されています。
ポリシーをコードで表現・管理することができます。

RBACポリシーの例

package app.rbac

roles_permissions := {
	"editor": {"delete", "create", "update", "read"},
	"writer": {"create", "update", "read"},
	"viewer": {"read"},
}

default allow := false

# ユーザーの持つロールの中に、要求された権限を持つものがあるかチェック
allow if {
	some role in input.roles
	input.permission in roles_permissions[role]
}

# adminロールを持っている場合は全ての操作を許可
allow if {
	"admin" in input.roles
}

ポリシーのテスト手法

ポリシーのテストは、同じくregoで記述することができます。
test_というプレフィックスをつけることで、テストとして認識されます。パッケージに、_testと付けるのは任意です。また、todo_test_のようなプレフィックスの場合、テストがSKIPPEDとして報告されます。

package app.rbac_test

import data.app.rbac

test_admin_can_delete if {
	rbac.allow with input as {"roles": ["admin"], "permission": "delete"}
}

# テーブル駆動テストとして書ける
test_rbac[title] if {
	some title, tt in {
		"viewer can not delete": {
			"roles": ["viewer"],
			"permission": "delete",
			"expect": false,
		},
		"admin can delete": {
            "roles": ["admin"],
       		"permission": "delete",
       		"expect": true,
        },
	}
	actual := rbac.allow with input as {"roles": tt.roles, "permission": tt.permission}
	tt.expect == actual
}

# これはスキップされる
todo_test_foo if {
    false
}

また、テストに必要なデータはYAMLもしくはJSONから読み込むことができます。
例えば、テストケースをYAMLで記述しておき、Regoでテストコードだけを書くことができます。

package app.rbac_test

import data.role_cases # YAMLからテストケースを読み込める

test_import_yaml[title] if {
	some title, tt in role_cases
	actual := rbac.allow with input as {"roles": tt.roles, "permission": tt.permission}
	tt.expect == actual
}
# table.yaml
role_cases:
  "viewer can not delete":
    roles: [ "viewer" ]
    permission: "delete"
    expect: false
  "admin can delete":
    roles: [ "admin" ]
    permission: "delete"
    expect: true
opa test -v .

テスト結果

rbac_test.rego:
data.app.rbac_test.todo_test_foo: SKIPPED
data.app.rbac_test.test_admin_can_delete: PASS (1.135833ms)
data.app.rbac_test.test_rbac: PASS (1.947334ms)
  admin can delete: PASS
  viewer can not delete: PASS

Goからの利用

Regoで書いたポリシーをOpenAgentPolicyを利用することで、Goから評価させることができます。
inputは、map[string]any型で渡すことができます。ですが、型の制約などを受けるために、jsonタグを使った structを宣言することを勧めます。

package main

import (
	"context"
	"fmt"

	"github.com/open-policy-agent/opa/v1/rego"
)

type Input struct {
	Roles      []string `json:"roles"`
	Permission string   `json:"permission"`
}

func main() {
	ctx := context.Background()
	query, err := rego.New(
		rego.Query("data.app.rbac.allow"),
		rego.Load([]string{"./opa/rbac.rego"}, nil),
	).PrepareForEval(ctx)
	if err != nil {
		panic(err)
	}

	inputs := []Input{
		{
			Roles:      []string{"admin"},
			Permission: "read",
		}, {
			Roles:      []string{"admin"},
			Permission: "write",
		}, {
			Roles:      []string{"viewer"},
			Permission: "create",
		},
	}

	for _, input := range inputs {
		results, err := query.Eval(ctx, rego.EvalInput(input))
		if err != nil {
			panic(err)
		}
		fmt.Printf(
			"roles: %v, permission: %v, result: %v\n",
			input.Roles, input.Permission, results.Allowed(),
		)
	}
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?