diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/app.go | 31 | ||||
| -rw-r--r-- | app/app_test.go | 62 | ||||
| -rw-r--r-- | app/init.go | 15 | ||||
| -rw-r--r-- | app/services/ability.go | 27 |
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 +} |
