Skip to content

Commit

Permalink
add all-tenants check authorization query
Browse files Browse the repository at this point in the history
  • Loading branch information
omer9564 committed Sep 7, 2023
1 parent b7f0669 commit 90bb00b
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 4 deletions.
108 changes: 108 additions & 0 deletions pkg/enforcement/all_tenants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package enforcement

import (
"bytes"
"encoding/json"
"github.com/permitio/permit-golang/pkg/errors"
"go.uber.org/zap"
"io"
"net/http"
)

type TenantDetails struct {
Key string `json:"key"`
Attributes map[string]interface{} `json:"attributes"`
}

type AllTenantsCheckResponse struct {
CheckResponse
Tenant TenantDetails `json:"tenant"`
}

type opaAllTenantsResponse struct {
Result *allowedTenantsResponse `json:"result"`
}

type allowedTenantsResponse struct {
AllowedTenants *[]AllTenantsCheckResponse `json:"allowed_tenants"`
}

func (e *PermitEnforcer) getAllTenantsCheckEndpoint() string {
return e.getEndpointByPolicyPackage(allTenantsPolicyPackage)
}

func (e *PermitEnforcer) parseAllTenantsResponse(res *http.Response) ([]AllTenantsCheckResponse, error) {
var result []AllTenantsCheckResponse
bodyBytes, err := io.ReadAll(res.Body)
if err != nil {
permitError := errors.NewPermitUnexpectedError(err, res)
e.logger.Error("error reading Permit.Bulk() response from PDP", zap.Error(permitError))
return nil, permitError
}
err = errors.HttpErrorHandle(err, res)
if err != nil {
e.logger.Error(string(bodyBytes), zap.Error(err))
return nil, err
}
if e.config.GetOpaUrl() != "" {
opaStruct := &opaAllTenantsResponse{
Result: &allowedTenantsResponse{
&result,
},
}

if err := json.Unmarshal(bodyBytes, opaStruct); err != nil {
permitError := errors.NewPermitUnexpectedError(err, res)
e.logger.Error("error unmarshalling Permit.BulkCheck() response from OPA", zap.Error(permitError))
return nil, err
}
} else {
pdpStruct := &allowedTenantsResponse{&result}
if err := json.Unmarshal(bodyBytes, &pdpStruct); err != nil {
permitError := errors.NewPermitUnexpectedError(err, res)
e.logger.Error("error unmarshalling Permit.BulkCheck response from PDP", zap.Error(permitError))
return nil, permitError
}
}

return result, nil
}

func (e *PermitEnforcer) AllTenantsCheck(user User, action Action, resource Resource, additionalContext ...map[string]string) ([]TenantDetails, error) {
reqAuthValue := "Bearer " + e.config.GetToken()

if additionalContext == nil {
additionalContext = make([]map[string]string, 0)
additionalContext = append(additionalContext, make(map[string]string))
}
jsonCheckReq, err := newJsonCheckRequest(e.config.GetOpaUrl(), user, action, resource, additionalContext[0])
if err != nil {
permitError := errors.NewPermitUnexpectedError(err, nil)
e.logger.Error("error marshalling Permit.AllTenantsCheck() request", zap.Error(permitError))
return nil, permitError
}
reqBody := bytes.NewBuffer(jsonCheckReq)
httpRequest, err := http.NewRequest(reqMethod, e.getAllTenantsCheckEndpoint(), reqBody)
if err != nil {
permitError := errors.NewPermitUnexpectedError(err, nil)
e.logger.Error("error creating Permit.AllTenantsCheck() request", zap.Error(permitError))
return nil, permitError
}
httpRequest.Header.Set(reqContentTypeKey, reqContentTypeValue)
httpRequest.Header.Set(reqAuthKey, reqAuthValue)
res, err := client.Do(httpRequest)
if err != nil {
permitError := errors.NewPermitUnexpectedError(err, res)
e.logger.Error("error sending Permit.AllTenantsCheck() request to PDP", zap.Error(permitError))
return nil, permitError
}
results, err := e.parseAllTenantsResponse(res)
if err != nil {
return nil, err
}
allowResults := make([]TenantDetails, len(results))
for result := range results {
allowResults[result] = results[result].Tenant
}
return allowResults, nil
}
14 changes: 10 additions & 4 deletions pkg/enforcement/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ type packageName string
type sidecarPath string

const (
mainPolicyPackage packageName = "permit.root"
bulkPolicyPackage packageName = "permit.bulk"
mainPolicyPackage packageName = "permit.root"
bulkPolicyPackage packageName = "permit.bulk"
allTenantsPolicyPackage packageName = "permit.all_tenants"
)

const (
mainPolicy sidecarPath = "/allowed"
bulkPolicy sidecarPath = "/allowed/bulk"
mainPolicy sidecarPath = "/allowed"
bulkPolicy sidecarPath = "/allowed/bulk"
allTenantsPolicy sidecarPath = "/allowed/all-tenants"
)

type checkOperationConfig struct {
Expand All @@ -42,4 +44,8 @@ var policyMap = map[packageName]checkOperationConfig{
sidecarPath: bulkPolicy,
opaPath: strings.Replace(string(bulkPolicyPackage), ".", "/", -1),
},
allTenantsPolicyPackage: {
sidecarPath: allTenantsPolicy,
opaPath: strings.Replace(string(allTenantsPolicyPackage), ".", "/", -1),
},
}
5 changes: 5 additions & 0 deletions pkg/permit/permit.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ func (c *Client) BulkCheck(requests ...enforcement.CheckRequest) ([]bool, error)
return c.enforcement.BulkCheck(requests...)
}

func (c *Client) AllTenantsCheck(user enforcement.User, action enforcement.Action, resource enforcement.Resource) ([]enforcement.TenantDetails, error) {
return c.enforcement.AllTenantsCheck(user, action, resource)
}

type PermitInterface interface {
Check(user enforcement.User, action enforcement.Action, resource enforcement.Resource) (bool, error)
BulkCheck(requests ...enforcement.CheckRequest) ([]bool, error)
AllTenantsCheck(request enforcement.CheckRequest) ([]enforcement.TenantDetails, error)
SyncUser(ctx context.Context, user models.UserCreate) (*models.UserRead, error)
}
15 changes: 15 additions & 0 deletions pkg/tests/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func TestIntegration(t *testing.T) {
actionKey := randKey("action")
actionGroupKey := randKey("actiongroup")
tenantKey := randKey("tenant")
secondTenantKey := randKey("tenant")

token := os.Getenv("PDP_API_KEY")
if token == "" {
Expand Down Expand Up @@ -218,6 +219,11 @@ func TestIntegration(t *testing.T) {
_, err = permitClient.Api.Tenants.Create(ctx, *tenantCreate)
assert.NoError(t, err)

secondTenantCreate := models.NewTenantCreate(secondTenantKey, secondTenantKey)
secondTenantCreate.SetAttributes(map[string]interface{}{"isSecond": true})
_, err = permitClient.Api.Tenants.Create(ctx, *secondTenantCreate)
assert.NoError(t, err)

tenants, err := permitClient.Api.Tenants.ListByAttributes(ctx, map[string]interface{}{
"marker": marker,
}, 1, 100)
Expand All @@ -240,4 +246,13 @@ func TestIntegration(t *testing.T) {
allowed, err := permitClient.Check(userCheck, "read", resourceCheck)
assert.NoError(t, err)
assert.True(t, allowed)

allowedTenants, err := permitClient.AllTenantsCheck(
userCheck,
"read",
resourceCheck.WithTenant("").Build(),
)
assert.Len(t, allowedTenants, 1)
assert.Equal(t, tenantKey, allowedTenants[0].Key)
assert.InDeltaMapValues(t, allowedTenants[0].Attributes, tenantCreate.Attributes, 0.0)
}

0 comments on commit 90bb00b

Please sign in to comment.