Skip to content

Commit 1d8fb82

Browse files
committed
papi: basic authorizer
1 parent a8bf7d0 commit 1d8fb82

File tree

5 files changed

+167
-14
lines changed

5 files changed

+167
-14
lines changed

components/public-api-server/go.mod

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.21
44

55
require (
66
github.com/AdaLogics/go-fuzz-headers v0.0.0-20220708163326-82d177caec6e
7+
github.com/authzed/authzed-go v0.10.0
78
github.com/bufbuild/connect-go v1.10.0
89
github.com/coreos/go-oidc/v3 v3.5.0
910
github.com/gitpod-io/gitpod/common-go v0.0.0-00010101000000-000000000000
@@ -17,18 +18,18 @@ require (
1718
github.com/google/go-cmp v0.5.9
1819
github.com/google/uuid v1.3.0
1920
github.com/gorilla/handlers v1.5.1
20-
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
21+
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
2122
github.com/hashicorp/golang-lru v0.5.4
2223
github.com/prometheus/client_golang v1.16.0
2324
github.com/redis/go-redis/v9 v9.0.2
2425
github.com/relvacode/iso8601 v1.1.0
2526
github.com/sirupsen/logrus v1.9.3
2627
github.com/sourcegraph/jsonrpc2 v0.0.0-20200429184054-15c2290dcb37
2728
github.com/spf13/cobra v1.4.0
28-
github.com/stretchr/testify v1.8.3
29+
github.com/stretchr/testify v1.8.4
2930
github.com/stripe/stripe-go/v72 v72.122.0
3031
github.com/zitadel/oidc v1.13.0
31-
golang.org/x/oauth2 v0.6.0
32+
golang.org/x/oauth2 v0.8.0
3233
google.golang.org/grpc v1.55.0
3334
google.golang.org/protobuf v1.31.0
3435
gopkg.in/square/go-jose.v2 v2.6.0
@@ -38,16 +39,21 @@ require (
3839
require (
3940
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
4041
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
42+
github.com/envoyproxy/protoc-gen-validate v1.0.1 // indirect
4143
github.com/gitpod-io/gitpod/components/scrubber v0.0.0-00010101000000-000000000000 // indirect
4244
github.com/go-logr/logr v1.2.4 // indirect
4345
github.com/go-logr/stdr v1.2.2 // indirect
46+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 // indirect
47+
github.com/jzelinskie/stringz v0.0.1 // indirect
4448
github.com/mitchellh/reflectwalk v1.0.2 // indirect
4549
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 // indirect
4650
go.opentelemetry.io/otel v1.16.0 // indirect
4751
go.opentelemetry.io/otel/metric v1.16.0 // indirect
4852
go.opentelemetry.io/otel/trace v1.16.0 // indirect
4953
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
5054
golang.org/x/sync v0.2.0 // indirect
55+
google.golang.org/genproto v0.0.0-20230526015343-6ee61e4f9d5f // indirect
56+
google.golang.org/genproto/googleapis/api v0.0.0-20230526161137-0005af68ea54 // indirect
5157
google.golang.org/genproto/googleapis/rpc v0.0.0-20230526161137-0005af68ea54 // indirect
5258
gorm.io/driver/mysql v1.4.4 // indirect
5359
gorm.io/plugin/opentelemetry v0.1.3 // indirect

components/public-api-server/go.sum

Lines changed: 30 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License.AGPL.txt in the project root for license information.
4+
5+
package auth
6+
7+
import (
8+
"context"
9+
"fmt"
10+
"net/http"
11+
12+
v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
13+
authzed "github.com/authzed/authzed-go/v1"
14+
"google.golang.org/grpc"
15+
"google.golang.org/grpc/credentials/insecure"
16+
17+
papi_config "github.com/gitpod-io/gitpod/components/public-api/go/config"
18+
"github.com/gitpod-io/gitpod/public-api-server/pkg/util"
19+
)
20+
21+
type SpiceDbAuthorizer struct {
22+
client *authzed.Client
23+
}
24+
25+
func NewSpiceDbAuthorizer(cfg *papi_config.SpiceDbAuthorizerConfig) (*SpiceDbAuthorizer, error) {
26+
client, err := authzed.NewClient(
27+
cfg.Address,
28+
grpc.WithTransportCredentials(insecure.NewCredentials()),
29+
)
30+
if err != nil {
31+
return nil, fmt.Errorf("failed to setup create SpiceDbAuthorizer: %w", err)
32+
}
33+
return &SpiceDbAuthorizer{
34+
client,
35+
}, nil
36+
}
37+
38+
func (a *SpiceDbAuthorizer) CheckPermissionOnOrganization(ctx context.Context, subjectId string, permission string, organizationId string) (bool, error) {
39+
resp, err := a.client.CheckPermission(ctx, &v1.CheckPermissionRequest{
40+
Subject: subject(subjectId),
41+
Permission: permission,
42+
Resource: object("organization", organizationId),
43+
Consistency: consistency(),
44+
})
45+
if err != nil {
46+
return false, util.NewApplicationError(http.StatusForbidden, "Error while calling CheckPermission: %w", err)
47+
}
48+
return resp.Permissionship == v1.CheckPermissionResponse_PERMISSIONSHIP_HAS_PERMISSION, nil
49+
}
50+
51+
func subject(subjectId string) *v1.SubjectReference {
52+
return &v1.SubjectReference{
53+
Object: &v1.ObjectReference{
54+
ObjectType: "user",
55+
ObjectId: subjectId,
56+
},
57+
}
58+
}
59+
60+
func object(objectType, objectId string) *v1.ObjectReference {
61+
return &v1.ObjectReference{
62+
ObjectType: objectType,
63+
ObjectId: objectId,
64+
}
65+
}
66+
67+
func consistency() *v1.Consistency {
68+
return &v1.Consistency{
69+
Requirement: &v1.Consistency_FullyConsistent{FullyConsistent: true},
70+
}
71+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License.AGPL.txt in the project root for license information.
4+
5+
package util
6+
7+
import (
8+
"errors"
9+
"fmt"
10+
)
11+
12+
type ApplicationError interface {
13+
error
14+
15+
// StatusCode returns the HTTP error code
16+
StatusCode() int
17+
18+
Unwrap() error
19+
}
20+
21+
func NewApplicationError(code int, msg string, err error) ApplicationError {
22+
return &applicationError{Code: code, Msg: fmt.Sprintf(msg+": %v", err)}
23+
}
24+
25+
type applicationError struct {
26+
Msg string `json:"message"`
27+
Code int `json:"code"`
28+
inner error `json:"-"`
29+
}
30+
31+
func (e *applicationError) StatusCode() int {
32+
return e.Code
33+
}
34+
func (e *applicationError) Error() string {
35+
return e.Msg
36+
}
37+
func (e *applicationError) Unwrap() error {
38+
return e.inner
39+
}
40+
41+
var _ ApplicationError = &applicationError{}
42+
43+
func MapErrToHttpStatusCode(err error) int {
44+
var appErr ApplicationError
45+
if errors.As(err, &appErr) {
46+
return appErr.StatusCode()
47+
}
48+
49+
return 500
50+
}

0 commit comments

Comments
 (0)