Skip to content

Commit

Permalink
feat(e2etest): add e2e test for hook overwrite case
Browse files Browse the repository at this point in the history
  • Loading branch information
mabdh committed May 30, 2024
1 parent cac2cd5 commit ef06d1b
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 3 deletions.
107 changes: 107 additions & 0 deletions test/e2e_test/smoke/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/suite"

"github.com/goto/shield/config"
"github.com/goto/shield/internal/store/postgres"
"github.com/goto/shield/pkg/db"
shieldv1beta1 "github.com/goto/shield/proto/v1beta1"
"github.com/goto/shield/test/e2e_test/testbench"
Expand Down Expand Up @@ -101,6 +102,36 @@ func (s *EndToEndProxySmokeTestSuite) TestProxyToEchoServer() {
defer res.Body.Close()
s.Assert().Equal(200, res.StatusCode)
})

s.Run("user not part of group will not be authenticated by middleware auth", func() {
groupDetail, err := s.client.GetGroup(context.Background(), &shieldv1beta1.GetGroupRequest{Id: s.groupID})
s.Require().NoError(err)

url := fmt.Sprintf("http://localhost:%d/api/resource_slug", s.appConfig.Proxy.Services[0].Port)
reqBodyMap := map[string]string{
"project": s.projID,
"name": "test-resource-group-slug",
"group_slug": groupDetail.GetGroup().GetSlug(),
}
reqBodyBytes, err := json.Marshal(reqBodyMap)
s.Require().NoError(err)

req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(reqBodyBytes))
s.Require().NoError(err)

req.Header.Set(testbench.IdentityHeader, "[email protected]")
req.Header.Set("X-Shield-Org", s.orgID)

res, err := http.DefaultClient.Do(req)
s.Require().NoError(err)

defer res.Body.Close()

s.Assert().Equal(401, res.StatusCode)
})
}

func (s *EndToEndProxySmokeTestSuite) TestResourceRelation() {
s.Run("resource created on echo server should persist in shieldDB", func() {
url := fmt.Sprintf("http://localhost:%d/api/resource", s.appConfig.Proxy.Services[0].Port)
reqBodyMap := map[string]string{
Expand Down Expand Up @@ -369,6 +400,7 @@ func (s *EndToEndProxySmokeTestSuite) TestProxyToEchoServer() {
}
s.Assert().Equal(s.userID, subjectID)
})

s.Run("resource created on echo server should persist in shieldDB when using user e-mail", func() {
userDetail, err := s.client.GetUser(context.Background(), &shieldv1beta1.GetUserRequest{Id: s.userID})
s.Require().NoError(err)
Expand Down Expand Up @@ -423,6 +455,81 @@ func (s *EndToEndProxySmokeTestSuite) TestProxyToEchoServer() {
})
}

func (s *EndToEndProxySmokeTestSuite) TestEdgeCases() {
s.Run("Two relations created in POST hook won't be overwritten when 1 relation in PUT hook is created", func() {
var (
resourceName = "test-resource-overwrite"
staticGroupUUID = "6b591fe0-fc94-4fd2-82bc-45f8a5d12a88"
)

userDetail, err := s.client.GetUser(context.Background(), &shieldv1beta1.GetUserRequest{Id: s.userID})
s.Require().NoError(err)
sqlRes, err := s.dbClient.DB.Exec(fmt.Sprintf("UPDATE groups SET id = '%s' WHERE slug = 'org1-group3'", staticGroupUUID))

Check failure on line 467 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / golangci

s.dbClient.DB undefined (type *db.Client has no field or method DB)

Check failure on line 467 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / e2e-smoke-test

s.dbClient.DB undefined (type *db.Client has no field or method DB)
s.Require().NoError(err)
rowsAffected, err := sqlRes.RowsAffected()
s.Require().NoError(err)
s.Require().Equal(int64(1), rowsAffected)

// POST
url := fmt.Sprintf("http://localhost:%d/api/resource", s.appConfig.Proxy.Services[0].Port)
reqBodyMap := map[string]string{
"project": s.projID,
"group": s.groupID,
"name": resourceName,
"user_email": userDetail.GetUser().GetEmail(),
}
reqBodyBytes, err := json.Marshal(reqBodyMap)
s.Require().NoError(err)

req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(reqBodyBytes))
s.Require().NoError(err)

req.Header.Set(testbench.IdentityHeader, "[email protected]")
req.Header.Set("X-Shield-Org", s.orgID)

res, err := http.DefaultClient.Do(req)
s.Require().NoError(err)
defer res.Body.Close()

s.Require().Equal(200, res.StatusCode)

// Validate resource & relation
var resourceShield = struct {
ID string `db:"id"`
Name string `db:"name"`
}{}

s.Require().NoError(s.dbClient.DB.Get(&resourceShield, fmt.Sprintf("SELECT id, name FROM resources WHERE name = '%s'", resourceName)))

Check failure on line 502 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / golangci

s.dbClient.DB undefined (type *db.Client has no field or method DB)

Check failure on line 502 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / e2e-smoke-test

s.dbClient.DB undefined (type *db.Client has no field or method DB)
s.Assert().Equal(resourceShield.Name, resourceName)

var relationsShield []postgres.Relation
s.Require().NoError(s.dbClient.DB.Select(&relationsShield, "SELECT * FROM relations WHERE role_id = 'entropy/firehose:owner'"))

Check failure on line 506 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / golangci

s.dbClient.DB undefined (type *db.Client has no field or method DB)

Check failure on line 506 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / e2e-smoke-test

s.dbClient.DB undefined (type *db.Client has no field or method DB)
s.Assert().Len(relationsShield, 2)

// PUT
req, err = http.NewRequest(http.MethodPut, url, bytes.NewBuffer(reqBodyBytes))
s.Require().NoError(err)

req.Header.Set(testbench.IdentityHeader, "[email protected]")
req.Header.Set("X-Shield-Org", s.orgID)

res, err = http.DefaultClient.Do(req)
s.Require().NoError(err)
defer res.Body.Close()

s.Require().Equal(200, res.StatusCode)

// Validate resource & relation
s.Require().NoError(s.dbClient.DB.Get(&resourceShield, fmt.Sprintf("SELECT id, name FROM resources WHERE name = '%s'", resourceName)))

Check failure on line 523 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / golangci

s.dbClient.DB undefined (type *db.Client has no field or method DB)

Check failure on line 523 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / e2e-smoke-test

s.dbClient.DB undefined (type *db.Client has no field or method DB)
s.Assert().Equal(resourceShield.Name, resourceName)

var updatedRelations []postgres.Relation
s.Require().NoError(s.dbClient.DB.Select(&updatedRelations, "SELECT * FROM relations WHERE role_id = 'entropy/firehose:owner'"))

Check failure on line 527 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / golangci

s.dbClient.DB undefined (type *db.Client has no field or method DB) (typecheck)

Check failure on line 527 in test/e2e_test/smoke/proxy_test.go

View workflow job for this annotation

GitHub Actions / e2e-smoke-test

s.dbClient.DB undefined (type *db.Client has no field or method DB)
fmt.Println(updatedRelations)
s.Assert().Len(updatedRelations, 2)
})
}

func TestEndToEndProxySmokeTestSuite(t *testing.T) {
suite.Run(t, new(EndToEndProxySmokeTestSuite))
}
34 changes: 34 additions & 0 deletions test/e2e_test/testbench/mockserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,38 @@ func startMockServer(ctx context.Context, logger *log.Zap, port int) {

reqBody["org"] = orgName
reqBody["urn"] = reqBody["name"]
reqBody["api"] = "POST"

respBytes, err := json.Marshal(reqBody)
if err != nil {
internalServerErrorWriter(w)
return
}

w.Write(respBytes)
}
updateResourceFn = func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
b, err := io.ReadAll(r.Body)
defer r.Body.Close()
if err != nil {
internalServerErrorWriter(w)
return
}

var reqBody map[string]string
if err := json.Unmarshal(b, &reqBody); err != nil {
internalServerErrorWriter(w)
return
}

var orgName = ""
if hOrg, ok := r.Header["X-Shield-Org"]; ok {
orgName = hOrg[0]
}

reqBody["org"] = orgName
reqBody["urn"] = reqBody["name"]
reqBody["api"] = "PUT"

respBytes, err := json.Marshal(reqBody)
if err != nil {
Expand All @@ -54,6 +86,8 @@ func startMockServer(ctx context.Context, logger *log.Zap, port int) {
w.Write([]byte("pong"))
})
router.POST("/api/resource", createResourceFn)
router.PUT("/api/resource", updateResourceFn)

router.POST("/api/resource_slug", createResourceFn)
router.POST("/api/resource_user_id", createResourceFn)
router.POST("/api/resource_user_email", createResourceFn)
Expand Down
6 changes: 3 additions & 3 deletions test/e2e_test/testbench/testbench.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ func initTestBench(ctx context.Context, appConfig *config.Shield, mockServerPort
URL: connMainPGExternal,
MaxIdleConns: 10,
MaxOpenConns: 10,
ConnMaxLifeTime: time.Millisecond * 100,
MaxQueryTimeoutInMS: time.Millisecond * 100,
ConnMaxLifeTime: time.Millisecond * 1000,
MaxQueryTimeoutInMS: time.Millisecond * 1000,
}

te.SpiceDBConfig = spicedb.Config{
Expand Down Expand Up @@ -256,7 +256,7 @@ func SetupTests(t *testing.T) (shieldv1beta1.ShieldServiceClient, *config.Shield
if err := BootstrapGroup(ctx, client, OrgAdminEmail, testDataPath); err != nil {
t.Fatal(err)
}
time.Sleep(10 * time.Second)
time.Sleep(5 * time.Second)
if err := AssignGroupManager(ctx, client, OrgAdminEmail); err != nil {
t.Fatal(err)
}
Expand Down
37 changes: 37 additions & 0 deletions test/e2e_test/testbench/testdata/configs/rules/rule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,43 @@ rules:
- name: create_resource
path: "/api/resource"
method: "POST"
hooks:
- name: authz
config:
action: authz_action
attributes:
resource:
key: urn
type: json_payload
source: response
project:
key: project
type: json_payload
source: request
group:
key: group
type: json_payload
source: request
organization:
key: X-Shield-Org
type: header
source: request
resource_type:
value: "firehose"
type: constant
additional_group:
value: 6b591fe0-fc94-4fd2-82bc-45f8a5d12a88
type: constant
relations:
- role: owner
subject_principal: shield/group
subject_id_attribute: group
- role: owner
subject_principal: shield/group
subject_id_attribute: additional_group
- name: update_resource
path: "/api/resource"
method: "PUT"
hooks:
- name: authz
config:
Expand Down
37 changes: 37 additions & 0 deletions test/e2e_test/testbench/testdata/configs/rules/rule.yamltpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,43 @@ rules:
- name: create_resource
path: "/api/resource"
method: "POST"
hooks:
- name: authz
config:
action: authz_action
attributes:
resource:
key: urn
type: json_payload
source: response
project:
key: project
type: json_payload
source: request
group:
key: group
type: json_payload
source: request
organization:
key: X-Shield-Org
type: header
source: request
resource_type:
value: "firehose"
type: constant
additional_group:
value: 6b591fe0-fc94-4fd2-82bc-45f8a5d12a88
type: constant
relations:
- role: owner
subject_principal: shield/group
subject_id_attribute: group
- role: owner
subject_principal: shield/group
subject_id_attribute: additional_group
- name: update_resource
path: "/api/resource"
method: "PUT"
hooks:
- name: authz
config:
Expand Down

0 comments on commit ef06d1b

Please sign in to comment.