Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make servicedata key public #86

Merged
merged 9 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
ports:
- "4000:80"
spicedb:
image: quay.io/authzed/spicedb:v1.0.0
image: authzed/spicedb:v1.32.0
ports:
- "8080:8080"
- "50051:50051"
Expand Down
2 changes: 1 addition & 1 deletion cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func BuildAPIDependencies(
serviceDataRepository := postgres.NewServiceDataRepository(dbc)
serviceDataService := servicedata.NewService(logger, serviceDataRepository, resourceService, relationService, projectService, userService, activityService)

relationAdapter := adapter.NewRelation(groupService, userService, relationService)
relationAdapter := adapter.NewRelation(groupService, userService, relationService, roleService)

dependencies := api.Deps{
OrgService: organizationService,
Expand Down
18 changes: 17 additions & 1 deletion internal/adapter/relation.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,36 @@ package adapter
import (
"context"
"fmt"
"slices"

"github.com/goto/shield/core/group"
"github.com/goto/shield/core/relation"
"github.com/goto/shield/core/role"
"github.com/goto/shield/core/user"
"github.com/goto/shield/internal/schema"
"github.com/goto/shield/pkg/uuid"
)

const WILDCARD = "*"

type Relation struct {
groupService *group.Service
userService *user.Service
relationService *relation.Service
roleService *role.Service
}

func NewRelation(
groupService *group.Service,
userService *user.Service,
relationService *relation.Service,
roleService *role.Service,
) *Relation {
return &Relation{
groupService: groupService,
userService: userService,
relationService: relationService,
roleService: roleService,
}
}

Expand All @@ -36,7 +43,16 @@ func (a Relation) TransformRelation(ctx context.Context, rlt relation.RelationV2
if rel.Subject.Namespace == schema.UserPrincipal || rel.Subject.Namespace == "user" {
userID := rel.Subject.ID

if !uuid.IsValid(userID) {
if userID == WILDCARD {
roleID := rel.Object.NamespaceID + ":" + rel.Subject.RoleID
ishanarya0 marked this conversation as resolved.
Show resolved Hide resolved
role, err := a.roleService.Get(ctx, roleID)
if err != nil {
return relation.RelationV2{}, fmt.Errorf("error fetching role: %s", err.Error())
}
if !slices.Contains(role.Types, schema.UserPrincipalWildcard) {
return relation.RelationV2{}, fmt.Errorf("%s does not allow wildcard for subject %s", rlt.Object.NamespaceID, rlt.Subject.Namespace)
}
} else if !uuid.IsValid(userID) {
fetchedUser, err := a.userService.GetByEmail(ctx, rel.Subject.ID)
if err != nil {
return relation.RelationV2{}, fmt.Errorf("%w: %s", relation.ErrFetchingUser, err.Error())
Expand Down
7 changes: 4 additions & 3 deletions internal/schema/predefined.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ const (
MembershipPermission = "membership"

// principals
UserPrincipal = "shield/user"
GroupPrincipal = "shield/group"
UserPrincipal = "shield/user"
GroupPrincipal = "shield/group"
UserPrincipalWildcard = "shield/user:*"
)

var InheritedRelations = map[string]bool{
Expand Down Expand Up @@ -131,7 +132,7 @@ var ServiceDataKeyConfig = NamespaceConfig{
},
Roles: map[string][]string{
EditorRole: {UserPrincipal, GroupPrincipal},
ViewerRole: {UserPrincipal, GroupPrincipal},
ViewerRole: {UserPrincipal, GroupPrincipal, UserPrincipalWildcard},
OwnerRole: {UserPrincipal, GroupPrincipal},
},
Permissions: map[string][]string{
Expand Down
3 changes: 2 additions & 1 deletion internal/store/postgres/role_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ func (r RoleRepository) Upsert(ctx context.Context, rl role.Role) (string, error
"metadata": goqu.L("$5"),
}).OnConflict(
goqu.DoUpdate("id", goqu.Record{
"name": goqu.L("$2"),
"types": goqu.L("$3"),
"metadata": goqu.L("$5"),
},
)).Returning("id").ToSQL()
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions internal/store/spicedb/schema_generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ func GenerateSchema(namespaceConfig schema.NamespaceConfigMapType) []string {

func processPrincipal(s string) string {
return map[string]string{
"shield/group": "shield/group#membership",
"shield/user": "shield/user",
"shield/group": "shield/group#membership",
"shield/user": "shield/user",
"shield/user:*": "shield/user:*",
}[s]
}
2 changes: 1 addition & 1 deletion internal/store/spicedb/schema_generator/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ func TestPredefinedSchema(t *testing.T) {
schema.PreDefinedSystemNamespaceConfig[schema.ServiceDataKeyNamespace] = schema.ServiceDataKeyConfig
actualPredefinedConfigs := makeDefnMap(GenerateSchema(schema.PreDefinedSystemNamespaceConfig))
expectedPredefinedConfigs := makeDefnMap(strings.Split(string(content), "\n--\n"))
assert.Equal(t, actualPredefinedConfigs, expectedPredefinedConfigs)
assert.Equal(t, expectedPredefinedConfigs, actualPredefinedConfigs)
}
2 changes: 1 addition & 1 deletion internal/store/spicedb/schema_generator/predefined_schema
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ definition shield/group {
--
definition shield/servicedata_key {
relation editor: shield/user | shield/group#membership
relation viewer: shield/user | shield/group#membership
relation viewer: shield/user | shield/group#membership | shield/user:*
relation owner: shield/user | shield/group#membership
permission edit = owner + editor + organization->owner + organization->editor + project->owner + project->editor
permission view = owner + editor + viewer + organization->owner + organization->editor + organization->viewer + project->owner + project->editor + project->viewer
Expand Down
37 changes: 37 additions & 0 deletions test/e2e_test/smoke/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/goto/shield/config"
"github.com/goto/shield/internal/schema"
shieldv1beta1 "github.com/goto/shield/proto/v1beta1"
"github.com/goto/shield/test/e2e_test/testbench"
"github.com/stretchr/testify/suite"
Expand Down Expand Up @@ -91,6 +92,42 @@ func (s *EndToEndAPISmokeTestSuite) TestUserAPI() {
})
}

func (s *EndToEndAPISmokeTestSuite) TestRelationsAPI() {
ctxOrgAdminAuth := metadata.NewOutgoingContext(context.Background(), metadata.New(map[string]string{
testbench.IdentityHeader: testbench.OrgAdminEmail,
}))

s.Run("1. should fail when trying to create wildcard relation", func() {
oRes, err := s.client.ListOrganizations(ctxOrgAdminAuth, &shieldv1beta1.ListOrganizationsRequest{})
s.Require().NoError(err)

_, err = s.client.CreateRelation(ctxOrgAdminAuth, &shieldv1beta1.CreateRelationRequest{
Body: &shieldv1beta1.RelationRequestBody{
ObjectId: oRes.Organizations[0].Id,
ObjectNamespace: schema.OrganizationNamespace,
Subject: schema.UserPrincipalWildcard,
RoleName: schema.OwnerRole,
},
})
s.Assert().Error(err)
})

s.Run("2. should allow relation creation with wildcard", func() {
res, err := s.client.ListResources(ctxOrgAdminAuth, &shieldv1beta1.ListResourcesRequest{})
s.Require().NoError(err)

_, err = s.client.CreateRelation(ctxOrgAdminAuth, &shieldv1beta1.CreateRelationRequest{
Body: &shieldv1beta1.RelationRequestBody{
ObjectId: res.Resources[0].Id,
ObjectNamespace: schema.ServiceDataKeyNamespace,
Subject: schema.UserPrincipalWildcard,
RoleName: schema.ViewerRole,
},
})
s.Assert().NoError(err)
})
}

func TestEndToEndAPISmokeTestSuite(t *testing.T) {
suite.Run(t, new(EndToEndAPISmokeTestSuite))
}
12 changes: 6 additions & 6 deletions test/e2e_test/testbench/spicedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import (

func migrateSpiceDB(logger log.Logger, network *docker.Network, pool *dockertest.Pool, pgConnString string) error {
resource, err := pool.RunWithOptions(&dockertest.RunOptions{
Repository: "quay.io/authzed/spicedb",
Tag: "v1.0.0",
Cmd: []string{"spicedb", "migrate", "head", "--datastore-engine", "postgres", "--datastore-conn-uri", pgConnString},
Repository: "authzed/spicedb",
Tag: "v1.32.0",
Cmd: []string{"migrate", "head", "--datastore-engine", "postgres", "--datastore-conn-uri", pgConnString},
NetworkID: network.ID,
}, func(config *docker.HostConfig) {
config.RestartPolicy = docker.RestartPolicy{
Expand Down Expand Up @@ -67,9 +67,9 @@ func migrateSpiceDB(logger log.Logger, network *docker.Network, pool *dockertest

func startSpiceDB(logger log.Logger, network *docker.Network, pool *dockertest.Pool, pgConnString string, preSharedKey string) (extPort string, res *dockertest.Resource, err error) {
res, err = pool.RunWithOptions(&dockertest.RunOptions{
Repository: "quay.io/authzed/spicedb",
Tag: "v1.0.0",
Cmd: []string{"spicedb", "serve", "--log-level", "debug", "--grpc-preshared-key", preSharedKey, "--grpc-no-tls", "--datastore-engine", "postgres", "--datastore-conn-uri", pgConnString},
Repository: "authzed/spicedb",
Tag: "v1.32.0",
Cmd: []string{"serve", "--log-level", "debug", "--grpc-preshared-key", preSharedKey, "--datastore-engine", "postgres", "--datastore-conn-uri", pgConnString},
ExposedPorts: []string{"50051/tcp"},
NetworkID: network.ID,
}, func(config *docker.HostConfig) {
Expand Down
3 changes: 2 additions & 1 deletion test/integration_test/rest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/goto/shield/core/project"
"github.com/goto/shield/core/relation"
"github.com/goto/shield/core/resource"
"github.com/goto/shield/core/role"
"github.com/goto/shield/core/rule"
"github.com/goto/shield/core/user"
"github.com/goto/shield/internal/adapter"
Expand Down Expand Up @@ -309,7 +310,7 @@ func buildPipeline(logger log.Logger, proxy http.Handler, ruleService *rule.Serv

func hookPipeline(log log.Logger) hook.Service {
rootHook := hook.New()
relationAdapter := adapter.NewRelation(&group.Service{}, &user.Service{}, &relation.Service{})
relationAdapter := adapter.NewRelation(&group.Service{}, &user.Service{}, &relation.Service{}, &role.Service{})
return authz_hook.New(log, rootHook, rootHook, &resource.Service{}, &relation.Service{}, relationAdapter, "X-Auth-Email")
}

Expand Down
Loading