...

Source file src/edge-infra.dev/pkg/sds/emergencyaccess/rules/rules.go

Documentation: edge-infra.dev/pkg/sds/emergencyaccess/rules

     1  package rulesengine
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  )
     7  
     8  func (reng RulesEngine) AddDefaultRules(ctx context.Context, rules WriteRules) (AddRuleResult, error) {
     9  	// validation
    10  	if err := rules.Validate(); err != nil {
    11  		return AddRuleResult{}, err
    12  	}
    13  
    14  	parts := splitPostDefaultRulesToRuleSegment(rules)
    15  	return reng.ds.AddDefaultRules(ctx, parts)
    16  }
    17  
    18  // AddDefaultRulesForPrivileges adds default rules for privileges based on the provided data.
    19  func (reng RulesEngine) AddDefaultRulesForPrivileges(ctx context.Context, data RuleSets) (AddRuleResult, error) {
    20  	if err := data.Validate(); err != nil {
    21  		return AddRuleResult{}, err
    22  	}
    23  	var parts []RuleSegment
    24  	for _, ruleSet := range data {
    25  		for _, command := range ruleSet.Commands {
    26  			ruleSegment := RuleSegment{
    27  				Command:   Command{Name: command},
    28  				Privilege: Privilege{Name: ruleSet.Privilege},
    29  			}
    30  			parts = append(parts, ruleSegment)
    31  		}
    32  	}
    33  	return reng.ds.AddDefaultRules(ctx, parts)
    34  }
    35  
    36  // GetDefaultRules retrieves the default rules. These consist of a Privilege with ID associated to a list of Commands and their IDs.
    37  // The optional `privilegeNames` argument can be used to filter the output to specific privileges
    38  func (reng RulesEngine) GetDefaultRules(ctx context.Context, privilegeNames ...string) ([]ReturnRuleSet, error) {
    39  	rules := make(map[Privilege][]Command)
    40  	res := []ReturnRuleSet{}
    41  	defaultRules, err := reng.ds.ReadAllDefaultRules(ctx)
    42  	if err != nil {
    43  		return res, err
    44  	}
    45  
    46  	// Convert slice of privilegeNames to a map for efficient lookups
    47  	privilegeNameMap := make(map[string]struct{})
    48  	for _, name := range privilegeNames {
    49  		privilegeNameMap[name] = struct{}{}
    50  	}
    51  
    52  	for _, rule := range defaultRules {
    53  		_, ok := privilegeNameMap[rule.Privilege.Name]
    54  		// If privilegeNames is empty, or the current rule's privilege is in the list, process it
    55  		if len(privilegeNameMap) == 0 || ok {
    56  			rules[rule.Privilege] = append(rules[rule.Privilege], rule.Command)
    57  		}
    58  	}
    59  
    60  	for priv, cmds := range rules {
    61  		res = append(res, ReturnRuleSet{Privilege: priv, Commands: cmds})
    62  	}
    63  	return res, nil
    64  }
    65  
    66  func splitPostDefaultRulesToRuleSegment(rules WriteRules) (parts []RuleSegment) {
    67  	for _, rule := range rules {
    68  		command := Command{Name: rule.Command}
    69  		for _, priv := range rule.Privileges {
    70  			privilege := Privilege{Name: priv}
    71  			parts = append(parts, RuleSegment{
    72  				Command:   command,
    73  				Privilege: privilege,
    74  			})
    75  		}
    76  	}
    77  	return parts
    78  }
    79  
    80  func (reng RulesEngine) ReadAllDefaultRules(ctx context.Context) ([]Rule, error) {
    81  	rulesegments, err := reng.ds.ReadAllDefaultRules(ctx)
    82  	if err != nil {
    83  		return []Rule{}, fmt.Errorf("error when reading all default rules: %s", err)
    84  	}
    85  	return assembleRules(rulesegments), nil
    86  }
    87  
    88  func (reng RulesEngine) ReadDefaultRulesForCommand(ctx context.Context, commandName string) ([]Rule, error) {
    89  	ruleSegments, err := reng.ds.ReadDefaultRulesForCommand(ctx, commandName)
    90  	if err != nil {
    91  		return []Rule{}, fmt.Errorf("error when reading default rules for command: %s", err)
    92  	}
    93  	return assembleRules(ruleSegments), nil
    94  }
    95  
    96  func (reng RulesEngine) DeleteDefaultRule(ctx context.Context, commandName, privilegeName string) (DeleteResult, error) {
    97  	return reng.ds.DeleteDefaultRule(ctx, commandName, privilegeName)
    98  }
    99  
   100  func assembleRules(ruleSegments []RuleSegment) []Rule {
   101  	rules := []Rule{}
   102  	for _, ruleSegment := range ruleSegments {
   103  		rules = appendRule(rules, ruleSegment)
   104  	}
   105  	return rules
   106  }
   107  
   108  func appendRule(rules []Rule, ruleSegment RuleSegment) []Rule {
   109  	if len(rules) == 0 {
   110  		return []Rule{{Command: ruleSegment.Command, Privileges: []Privilege{ruleSegment.Privilege}}}
   111  	}
   112  	for idx, rule := range rules {
   113  		if rule.Command.ID == ruleSegment.Command.ID {
   114  			// dataset handles duplicate instances for us so we dont need to check here
   115  			rules[idx].Privileges = append(rule.Privileges, ruleSegment.Privilege)
   116  			return rules
   117  		}
   118  	}
   119  	rules = append(rules, Rule{Command: ruleSegment.Command, Privileges: []Privilege{ruleSegment.Privilege}})
   120  	return rules
   121  }
   122  

View as plain text