generated from layer5io/layer5-repo-template
-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #348 from meshery/revert-347-revert-345-rego
WIP [Policy] init rego instance""
- Loading branch information
Showing
3 changed files
with
87 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) | ||
} |