Commit c75ceda
Changed files (6)
pkg
policies
test
pkg/policies/init.go
@@ -0,0 +1,72 @@
+package policies
+
+import (
+ "embed"
+ _ "embed"
+ "encoding/json"
+ "fmt"
+ "io/fs"
+ "log"
+
+ "github.com/cedar-policy/cedar-go"
+ "github.com/cedar-policy/cedar-go/types"
+ "github.com/xlgmokha/x/pkg/x"
+)
+
+//go:embed *.cedar
+var files embed.FS
+
+var All *cedar.PolicySet = cedar.NewPolicySet()
+
+const entitiesJSON = `[
+ {
+ "uid": { "type": "User", "id": "alice" },
+ "attrs": { "age": 18 },
+ "parents": []
+ },
+ {
+ "uid": { "type": "Photo", "id": "VacationPhoto94.jpg" },
+ "attrs": {},
+ "parents": [{ "type": "Album", "id": "jane_vacation" }]
+ }
+]`
+
+func init() {
+ err := fs.WalkDir(files, ".", func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+
+ if d.IsDir() {
+ return nil
+ }
+
+ content, err := fs.ReadFile(files, path)
+ if err != nil {
+ return err
+ }
+
+ var policy cedar.Policy
+ if err := policy.UnmarshalCedar(content); err != nil {
+ return err
+ }
+
+ All.Add(cedar.PolicyID(path), &policy)
+ return nil
+ })
+
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func Allowed(request cedar.Request) bool {
+ var entities cedar.EntityMap
+ x.Check(json.Unmarshal([]byte(entitiesJSON), &entities))
+
+ ok, diagnostic := All.IsAuthorized(entities, request)
+ if len(diagnostic.Errors) > 0 || len(diagnostic.Reasons) > 0 {
+ fmt.Printf("%v %v\n", diagnostic.Errors, diagnostic.Reasons)
+ }
+ return ok == types.Allow
+}
pkg/policies/project.cedar
@@ -0,0 +1,5 @@
+permit (
+ principal == User::"alice",
+ action == Action::"view",
+ resource in Album::"jane_vacation"
+);
pkg/rpc/ability_handler.go
@@ -2,14 +2,25 @@ package rpc
import (
context "context"
+
+ "github.com/cedar-policy/cedar-go"
+ "gitlab.com/mokhax/spike/pkg/policies"
)
type AbilityHandler struct {
UnimplementedAbilityServer
}
+func NewAbilityHandler() *AbilityHandler {
+ return &AbilityHandler{}
+}
+
func (h *AbilityHandler) Allowed(ctx context.Context, req *AllowRequest) (*AllowReply, error) {
- return &AllowReply{
- Result: false,
- }, nil
+ ok := policies.Allowed(cedar.Request{
+ Principal: cedar.NewEntityUID("User", cedar.String(req.Subject)),
+ Action: cedar.NewEntityUID("Action", cedar.String(req.Permission)),
+ Resource: cedar.NewEntityUID("Album", cedar.String(req.Resource)),
+ Context: cedar.NewRecord(cedar.RecordMap{}),
+ })
+ return &AllowReply{Result: ok}, nil
}
pkg/rpc/server.go
@@ -6,6 +6,6 @@ import (
func New(options ...grpc.ServerOption) *grpc.Server {
server := grpc.NewServer(options...)
- RegisterAbilityServer(server, &AbilityHandler{})
+ RegisterAbilityServer(server, NewAbilityHandler())
return server
}
pkg/rpc/server_test.go
@@ -31,7 +31,7 @@ func TestServer(t *testing.T) {
defer connection.Close()
client := NewAbilityClient(connection)
- t.Run("returns a result", func(t *testing.T) {
+ t.Run("returns false", func(t *testing.T) {
reply, err := client.Allowed(t.Context(), &AllowRequest{
Subject: "",
Permission: "",
@@ -40,4 +40,14 @@ func TestServer(t *testing.T) {
require.NoError(t, err)
assert.False(t, reply.Result)
})
+
+ t.Run("returns true", func(t *testing.T) {
+ reply, err := client.Allowed(t.Context(), &AllowRequest{
+ Subject: "alice",
+ Permission: "view",
+ Resource: "jane_vacation",
+ })
+ require.NoError(t, err)
+ assert.True(t, reply.Result)
+ })
}
test/e2e_test.go
@@ -20,6 +20,10 @@ import (
)
func TestAuthx(t *testing.T) {
+ if env.Fetch("SKIP_E2E", "") != "" {
+ t.Skip()
+ }
+
_ = playwright.Install()
pw := x.Must(playwright.Run())