From 7eb46060b33af16e10a3b5d0b828f7c305bac16c Mon Sep 17 00:00:00 2001 From: Akshat Mahajan Date: Tue, 1 Dec 2020 01:57:07 -0500 Subject: [PATCH] Export intercepts --- policies.go | 34 +++++++++++++++++++++++++--------- policies_test.go | 10 +++++++++- public_methods.go | 11 +++++++++-- testing/files/example.json | 8 ++++++++ 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/policies.go b/policies.go index e23252f..51f6899 100644 --- a/policies.go +++ b/policies.go @@ -14,14 +14,23 @@ import ( const environment_variable string = "GRPC_PRIVACY_POLICY_LOCATION" var loaded_policies map[string]Conditions +var loaded_intercepts map[string]ContextPair // run on library import func init() { refreshPolicies() } +type ContextPair map[string][]string + type PolicyDocument struct { - Policies []Policy `json:"Policies"` + Policies []Policy `json:"Policies"` + Intercepts *[]InterceptPolicy `json:"RequestValidation",omitEmpty` +} + +type InterceptPolicy struct { + FullName string `json:"MethodName"` + Pairs ContextPair `json:"MatchingContext"` } type Policy struct { @@ -42,19 +51,19 @@ type ConditionStatement struct { } // Pull policies from the stored policy file. -func loadPolicies(file_path string) (map[string]Conditions, error) { +func loadPolicies(file_path string) (map[string]Conditions, map[string]ContextPair, error) { path, err := filepath.Abs(file_path) if err != nil { log.Errorf("Could not resolve provided filepath %s", file_path) - return nil, err + return nil, nil, err } jsonFile, err := os.Open(path) defer jsonFile.Close() if err != nil { log.Errorf("Could not find file at provided filepath %s", file_path) - return nil, err + return nil, nil, err } byteValue, _ := ioutil.ReadAll(jsonFile) @@ -62,29 +71,36 @@ func loadPolicies(file_path string) (map[string]Conditions, error) { json.Unmarshal(byteValue, &document) policies := make(map[string]Conditions) + intercepts := make(map[string]ContextPair) for _, policy := range document.Policies { key := fmt.Sprintf("%s.%s", strings.Title(policy.Message), strings.Title(policy.Field)) policies[key] = policy.Conditions } + if document.Intercepts != nil { + for _, intercept := range *(document.Intercepts) { + intercepts[intercept.FullName] = intercept.Pairs + } + } - return policies, nil + return policies, intercepts, nil } // Fetches the policies and stores them in memory. Called once in init(). // Can be called in testing code as well. func refreshPolicies() { - policies, err := loadPoliciesFromEnvironmentVariable() + policies, intercepts, err := loadPoliciesFromEnvironmentVariable() if err != nil { log.Warnf("Error fetching policies. All actions will be allowed and no policies will be checked.") } loaded_policies = policies + loaded_intercepts = intercepts } -func loadPoliciesFromEnvironmentVariable() (map[string]Conditions, error) { +func loadPoliciesFromEnvironmentVariable() (map[string]Conditions, map[string]ContextPair, error) { path := os.Getenv(environment_variable) if len(path) == 0 { log.Warnf("%s not set", environment_variable) - return nil, nil + return nil, nil, nil } return loadPolicies(path) } @@ -118,7 +134,7 @@ func isActionAllowed(messageName protoreflect.Name, attributeName protoreflect.N chosen_condition = conditions.ModifyConditions } - log.Debugf("Because %+v was chosen for action, using specific condition for that action: %+v", key, chosen_condition) + log.Debugf("Because %+v was chosen for action, using specific condition for that action: %+v", act, chosen_condition) if chosen_condition == nil { return true diff --git a/policies_test.go b/policies_test.go index 37087fb..7277437 100644 --- a/policies_test.go +++ b/policies_test.go @@ -20,7 +20,7 @@ func setupExamplePolicy(t *testing.T, filepath string) func(t *testing.T) { func TestParsing(t *testing.T) { - policies, err := loadPolicies("testing/files/example.json") + policies, intercepts, err := loadPolicies("testing/files/example.json") if err != nil { t.Errorf("Encountered error opening the file %+v", err) } @@ -38,6 +38,14 @@ func TestParsing(t *testing.T) { }, } + if intercepts["foo"] == nil || intercepts["foo"]["bar"] == nil { + t.Errorf("Expected map[foo:map[bar:[baz]]]` in intercepts, got %+v", intercepts) + } + + if len(intercepts["foo"]["bar"]) != 1 || intercepts["foo"]["bar"][0] != "baz" { + t.Errorf("Expected map[foo:map[bar:[baz]]]` in intercepts, got %+v", intercepts) + } + for expected_key, expected_value := range expected { if found_value, ok := policies[expected_key]; ok { if !reflect.DeepEqual(found_value, expected_value) { diff --git a/public_methods.go b/public_methods.go index 7145093..2b9eeaf 100644 --- a/public_methods.go +++ b/public_methods.go @@ -1,6 +1,7 @@ package privacy import ( + "errors" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" ) @@ -43,8 +44,14 @@ func Unmarshal(b []byte, m proto.Message) error { return err } -// Marshal returns the wire-format encoding of m. +// Marshal returns the wire-format encoding of m. Assumes the action is `printing`. func Marshal(m proto.Message) ([]byte, error) { - recursiveCrypt(m, decryptMode) + recursiveCrypt(m, permissionedDecryptMode) return proto.Marshal(m) } + +// A function that returns a copy of all the loaded intercept methods +// TODO: Actually return a copy, not a reference to the loaded intercept itself! +func ExportContextPolicies() map[string]ContextPair { + return loaded_intercepts +} diff --git a/testing/files/example.json b/testing/files/example.json index 01a233e..3d66a90 100644 --- a/testing/files/example.json +++ b/testing/files/example.json @@ -18,5 +18,13 @@ "Field": "message", "Conditions": {} } + ], + "RequestValidation": [ + { + "MethodName": "foo", + "MatchingContext": { + "bar": ["baz"] + } + } ] } \ No newline at end of file