From 2ccee14dfc4ebd3d8448a330fbf7af000bdc8903 Mon Sep 17 00:00:00 2001
From: Yordan Kinkov <yordan.kinkov@vereign.com>
Date: Thu, 7 Apr 2022 12:46:47 +0300
Subject: [PATCH] #15 add ENV variables to policy evaluation runtime

---
 internal/service/policy/service.go | 34 +++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/internal/service/policy/service.go b/internal/service/policy/service.go
index a9f6616a..a12c7f56 100644
--- a/internal/service/policy/service.go
+++ b/internal/service/policy/service.go
@@ -2,7 +2,10 @@ package policy
 
 import (
 	"context"
+	"os"
+	"strings"
 
+	"github.com/open-policy-agent/opa/ast"
 	"github.com/open-policy-agent/opa/rego"
 	"go.uber.org/zap"
 
@@ -18,13 +21,19 @@ type Storage interface {
 
 type Service struct {
 	storage Storage
-	logger  *zap.Logger
+
+	runtimeObj *ast.Term // object to pass to each rego query
+
+	logger *zap.Logger
 }
 
 func New(storage Storage, logger *zap.Logger) *Service {
+	runtimeObj := getRuntimeObject()
+
 	return &Service{
-		storage: storage,
-		logger:  logger,
+		storage:    storage,
+		runtimeObj: runtimeObj,
+		logger:     logger,
 	}
 }
 
@@ -52,6 +61,7 @@ func (s *Service) Evaluate(ctx context.Context, req *policy.EvaluateRequest) (*p
 	query, err := rego.New(
 		rego.Module(pol.Filename, pol.Rego),
 		rego.Query("result = data.gaiax.result"),
+		rego.Runtime(s.runtimeObj),
 	).PrepareForEval(ctx)
 	if err != nil {
 		logger.Error("error preparing rego query", zap.Error(err))
@@ -139,3 +149,21 @@ func (s *Service) Unlock(ctx context.Context, req *policy.UnlockRequest) error {
 
 	return nil
 }
+
+// getRuntimeObject adds environment variables to an OPA object
+// which later is passed to rego query's runtime
+func getRuntimeObject() *ast.Term {
+	obj := ast.NewObject()
+	env := ast.NewObject()
+	for _, s := range os.Environ() {
+		parts := strings.SplitN(s, "=", 2)
+		if len(parts) == 1 {
+			env.Insert(ast.StringTerm(parts[0]), ast.NullTerm())
+		} else if len(parts) > 1 {
+			env.Insert(ast.StringTerm(parts[0]), ast.StringTerm(parts[1]))
+		}
+	}
+	obj.Insert(ast.StringTerm("env"), ast.NewTerm(env))
+
+	return ast.NewTerm(obj)
+}
-- 
GitLab