summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/app.go31
-rw-r--r--app/app_test.go62
-rw-r--r--app/init.go15
-rw-r--r--app/services/ability.go27
4 files changed, 135 insertions, 0 deletions
diff --git a/app/app.go b/app/app.go
new file mode 100644
index 00000000..a9923554
--- /dev/null
+++ b/app/app.go
@@ -0,0 +1,31 @@
+package app
+
+import (
+ "net/http"
+
+ "github.com/rs/zerolog"
+ "github.com/xlgmokha/x/pkg/ioc"
+ "github.com/xlgmokha/x/pkg/log"
+ "gitlab.com/gitlab-org/software-supply-chain-security/authorization/authz.d/app/services"
+ "gitlab.com/gitlab-org/software-supply-chain-security/authorization/authz.d/pkg/rpc"
+)
+
+func New() http.Handler {
+ mux := http.NewServeMux()
+ for _, handler := range handlers() {
+ mux.Handle(handler.PathPrefix(), handler)
+ }
+
+ mux.Handle("/health", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ }))
+
+ logger := ioc.MustResolve[*zerolog.Logger](ioc.Default)
+ return log.HTTP(logger)(mux)
+}
+
+func handlers() []rpc.TwirpServer {
+ return []rpc.TwirpServer{
+ rpc.NewAbilityServer(services.NewAbilityService()),
+ }
+}
diff --git a/app/app_test.go b/app/app_test.go
new file mode 100644
index 00000000..8aaaaee0
--- /dev/null
+++ b/app/app_test.go
@@ -0,0 +1,62 @@
+package app
+
+import (
+ http "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/software-supply-chain-security/authorization/authz.d/pkg/rpc"
+)
+
+func TestApp(t *testing.T) {
+ handler := New()
+ srv := httptest.NewServer(handler)
+ defer srv.Close()
+
+ t.Run("Ability.Allowed", func(t *testing.T) {
+ client := rpc.NewAbilityProtobufClient(srv.URL, &http.Client{})
+
+ t.Run("forbids", func(t *testing.T) {
+ reply, err := client.Allowed(t.Context(), &rpc.AllowRequest{
+ Subject: "",
+ Permission: "",
+ Resource: "",
+ })
+ require.NoError(t, err)
+ assert.False(t, reply.Result)
+ })
+
+ t.Run("allows alice:view:jane_vacation", func(t *testing.T) {
+ reply, err := client.Allowed(t.Context(), &rpc.AllowRequest{
+ Subject: "gid://example/User/alice",
+ Permission: "view",
+ Resource: "gid://example/Album/jane_vacation",
+ })
+ require.NoError(t, err)
+ assert.True(t, reply.Result)
+ })
+
+ t.Run("allows gid://User/1 read gid://Organization/2", func(t *testing.T) {
+ reply, err := client.Allowed(t.Context(), &rpc.AllowRequest{
+ Subject: "gid://example/User/1",
+ Permission: "read",
+ Resource: "gid://example/Organization/2",
+ })
+ require.NoError(t, err)
+ assert.True(t, reply.Result)
+ })
+ })
+
+ t.Run("GET /health", func(t *testing.T) {
+ t.Run("returns OK", func(t *testing.T) {
+ r := httptest.NewRequest("GET", "/health", nil)
+ w := httptest.NewRecorder()
+
+ handler.ServeHTTP(w, r)
+
+ assert.Equal(t, http.StatusOK, w.Code)
+ })
+ })
+}
diff --git a/app/init.go b/app/init.go
new file mode 100644
index 00000000..f5d1dc4b
--- /dev/null
+++ b/app/init.go
@@ -0,0 +1,15 @@
+package app
+
+import (
+ "os"
+
+ "github.com/rs/zerolog"
+ "github.com/xlgmokha/x/pkg/ioc"
+ "github.com/xlgmokha/x/pkg/log"
+)
+
+func init() {
+ ioc.RegisterSingleton[*zerolog.Logger](ioc.Default, func() *zerolog.Logger {
+ return log.New(os.Stdout, log.Fields{})
+ })
+}
diff --git a/app/services/ability.go b/app/services/ability.go
new file mode 100644
index 00000000..871a9a9b
--- /dev/null
+++ b/app/services/ability.go
@@ -0,0 +1,27 @@
+package services
+
+import (
+ context "context"
+
+ "github.com/cedar-policy/cedar-go"
+ "gitlab.com/gitlab-org/software-supply-chain-security/authorization/authz.d/pkg/gid"
+ "gitlab.com/gitlab-org/software-supply-chain-security/authorization/authz.d/pkg/policies"
+ "gitlab.com/gitlab-org/software-supply-chain-security/authorization/authz.d/pkg/rpc"
+)
+
+type AbilityService struct {
+}
+
+func NewAbilityService() *AbilityService {
+ return &AbilityService{}
+}
+
+func (h *AbilityService) Allowed(ctx context.Context, req *rpc.AllowRequest) (*rpc.AllowReply, error) {
+ ok := policies.Allowed(cedar.Request{
+ Principal: gid.NewEntityUID(req.Subject),
+ Action: cedar.NewEntityUID("Permission", cedar.String(req.Permission)),
+ Resource: gid.NewEntityUID(req.Resource),
+ Context: cedar.NewRecord(cedar.RecordMap{}),
+ })
+ return &rpc.AllowReply{Result: ok}, nil
+}