Skip to content

Commit

Permalink
Merge pull request #348 from meshery/revert-347-revert-345-rego
Browse files Browse the repository at this point in the history
WIP [Policy] init rego instance""
  • Loading branch information
Mohd Uzair authored Aug 16, 2023
2 parents 1dba678 + 7af07e0 commit 25d783f
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 11 deletions.
2 changes: 1 addition & 1 deletion helpers/component_info.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "meshkit",
"type": "library",
"next_error_code": 11097
"next_error_code": 11100
}
16 changes: 16 additions & 0 deletions models/meshmodel/core/policies/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package policies

import "github.com/layer5io/meshkit/errors"

const (
ErrPrepareForEvalCode = "11098"
ErrEvalCode = "11099"
)

func ErrPrepareForEval(err error) error {
return errors.New(ErrPrepareForEvalCode, errors.Alert, []string{"error preparing for evaluation"}, []string{err.Error()}, []string{"query might be empty", "rego store provided without associated transaction", "uncommitted transaction"}, []string{"please provide the transaction for the loaded store"})
}

func ErrEval(err error) error {
return errors.New(ErrEvalCode, errors.Alert, []string{"error evaluating policy for the given input"}, []string{err.Error()}, []string{"The policy query is invalid, see: https://github.com/open-policy-agent/opa/blob/main/rego/resultset.go (Allowed func)"}, []string{"please provide a valid non-empty query"})
}
80 changes: 70 additions & 10 deletions models/meshmodel/core/policies/rego_policy_relationship.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,99 @@ package policies

import (
"context"
"fmt"
"encoding/json"
"io/fs"
"os"
"path/filepath"
"strings"

"github.com/layer5io/meshkit/models/meshmodel/core/v1alpha1"
"github.com/layer5io/meshkit/utils"
"github.com/open-policy-agent/opa/rego"
"github.com/open-policy-agent/opa/storage"
"github.com/open-policy-agent/opa/storage/inmem"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
)

// RegoPolicyHandler takes the required inputs and run the query against all the policy files provided
func RegoPolicyHandler(ctx context.Context, policyDir []string, regoQueryString string, designFile []byte) (map[string]interface{}, error) {
regoPolicyLoader := rego.Load(policyDir, nil)
type Rego struct {
store storage.Store
ctx context.Context
transaction storage.Transaction
policyDir string
}

func NewRegoInstance(policyDir string, relationshipDir string) (*Rego, error) {
var relationships []v1alpha1.RelationshipDefinition
ctx := context.Background()

err := filepath.Walk(relationshipDir, func(path string, info fs.FileInfo, err error) error {
var relationship v1alpha1.RelationshipDefinition
if !info.IsDir() {
byt, err := os.ReadFile(path)
if err != nil {
return utils.ErrReadingLocalFile(err)
}
err = json.Unmarshal(byt, &relationship)
if err != nil {
return utils.ErrUnmarshal(err)
}
relationships = append(relationships, relationship)
}
return nil
})

if err != nil {
return nil, err
}

data := mapRelationshipsWithSubType(&relationships)
store := inmem.NewFromObject(data)
txn, _ := store.NewTransaction(ctx, storage.WriteParams)

return &Rego{
store: store,
ctx: ctx,
transaction: txn,
policyDir: policyDir,
}, nil
}

func mapRelationshipsWithSubType(relationships *[]v1alpha1.RelationshipDefinition) map[string]interface{} {
relMap := make(map[string]interface{}, len(*relationships))
for _, relationship := range *relationships {
relMap[strings.ToLower(relationship.SubType)] = relationship
}
return relMap
}

// RegoPolicyHandler takes the required inputs and run the query against all the policy files provided
func (r *Rego) RegoPolicyHandler(regoQueryString string, designFile []byte) (map[string]interface{}, error) {
regoEngine, err := rego.New(
rego.Query(regoQueryString),
regoPolicyLoader,
).PrepareForEval(ctx)
rego.Load([]string{r.policyDir}, nil),
rego.Store(r.store),
rego.Transaction(r.transaction),
).PrepareForEval(r.ctx)
if err != nil {
logrus.Error("error preparing for evaluation", err)
return nil, ErrPrepareForEval(err)
}

var input map[string]interface{}
err = yaml.Unmarshal((designFile), &input)
if err != nil {
return nil, err
return nil, utils.ErrUnmarshal(err)
}

eval_result, err := regoEngine.Eval(ctx, rego.EvalInput(input))
eval_result, err := regoEngine.Eval(r.ctx, rego.EvalInput(input))
if err != nil {
return nil, err
return nil, ErrEval(err)
}

if !eval_result.Allowed() {
return eval_result[0].Expressions[0].Value.(map[string]interface{}), nil
}

return nil, fmt.Errorf("error evaluation rego response, the result is not returning the expressions, The policy query is invalid, see: github.com/open-policy-agent/[email protected]/rego/resultset.go (Allowed func)")
return nil, ErrEval(err)
}

0 comments on commit 25d783f

Please sign in to comment.