From 30bbdad4ef99449f29f412d0b770e4b9f76ede42 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 28 Mar 2025 17:49:09 -0600 Subject: refactor: move authorizers into authz package --- pkg/authz/casbin.go | 43 +++++++++++++++++++++++++++++++++++++++++++ pkg/authz/cedar.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 pkg/authz/casbin.go create mode 100644 pkg/authz/cedar.go (limited to 'pkg/authz') diff --git a/pkg/authz/casbin.go b/pkg/authz/casbin.go new file mode 100644 index 00000000..99dcc8ec --- /dev/null +++ b/pkg/authz/casbin.go @@ -0,0 +1,43 @@ +package authz + +import ( + "fmt" + "net" + "net/http" + + "github.com/casbin/casbin/v3" + "github.com/xlgmokha/x/pkg/x" + xlog "gitlab.com/mokhax/spike/pkg/log" +) + +func WithCasbin() Authorizer { + enforcer := x.Must(casbin.NewEnforcer("casbin.conf", "casbin.csv")) + + return AuthorizerFunc(func(r *http.Request) bool { + host, _, err := net.SplitHostPort(r.Host) + if err != nil { + xlog.WithFields(r, xlog.Fields{"error": err}) + return false + } + + subject, found := TokenFrom(r).Subject() + if !found { + subject = "*" + } + ok, err := enforcer.Enforce(subject, host, r.Method, r.URL.Path) + if err != nil { + xlog.WithFields(r, xlog.Fields{"error": err}) + return false + } + + fmt.Printf("%v: %v -> %v %v%v\n", ok, subject, r.Method, host, r.URL.Path) + xlog.WithFields(r, xlog.Fields{ + "ok": ok, + "subject": subject, + "action": r.Method, + "domain": host, + "object": r.URL.Path, + }) + return ok + }) +} diff --git a/pkg/authz/cedar.go b/pkg/authz/cedar.go new file mode 100644 index 00000000..1d952651 --- /dev/null +++ b/pkg/authz/cedar.go @@ -0,0 +1,53 @@ +package authz + +import ( + "encoding/json" + "fmt" + "net" + "net/http" + "os" + + cedar "github.com/cedar-policy/cedar-go" + "github.com/cedar-policy/cedar-go/types" + "github.com/xlgmokha/x/pkg/x" + xlog "gitlab.com/mokhax/spike/pkg/log" +) + +func WithCedar() Authorizer { + var policy cedar.Policy + x.Check(policy.UnmarshalCedar(x.Must(os.ReadFile("cedar.conf")))) + + policies := cedar.NewPolicySet() + policies.Add("cedar.conf", &policy) + + var entities cedar.EntityMap + if err := json.Unmarshal(x.Must(os.ReadFile("cedar.json")), &entities); err != nil { + xlog.Logger.Error("Error", "error", err) + return nil + } + + return AuthorizerFunc(func(r *http.Request) bool { + host, _, err := net.SplitHostPort(r.Host) + if err != nil { + return false + } + + subject, found := TokenFrom(r).Subject() + if !found { + subject = "*" + } + + req := cedar.Request{ + Principal: cedar.NewEntityUID("Subject", cedar.String(subject)), + Action: cedar.NewEntityUID("Action", cedar.String(r.Method)), + Resource: cedar.NewEntityUID("Path", cedar.String(r.URL.Path)), + Context: cedar.NewRecord(cedar.RecordMap{ + "Host": cedar.String(host), + }), + } + + ok, diagnostic := policies.IsAuthorized(entities, req) + fmt.Printf("%v: %v -> %v %v%v %v\n", ok, subject, r.Method, host, r.URL.Path, diagnostic.Reasons) + return ok == types.Allow + }) +} -- cgit v1.2.3