github.com/in-toto/in-toto-golang@v0.9.1-0.20240517212500-990269f763cf/in_toto/rulelib.go (about) 1 package in_toto 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // An error message issued in UnpackRule if it receives a malformed rule. 9 var errorMsg = "Wrong rule format, available formats are:\n" + 10 "\tMATCH <pattern> [IN <source-path-prefix>] WITH (MATERIALS|PRODUCTS)" + 11 " [IN <destination-path-prefix>] FROM <step>,\n" + 12 "\tCREATE <pattern>,\n" + 13 "\tDELETE <pattern>,\n" + 14 "\tMODIFY <pattern>,\n" + 15 "\tALLOW <pattern>,\n" + 16 "\tDISALLOW <pattern>,\n" + 17 "\tREQUIRE <filename>\n\n" 18 19 /* 20 UnpackRule parses the passed rule and extracts and returns the information 21 required for rule processing. It can be used to verify if a rule has a valid 22 format. Available rule formats are: 23 24 MATCH <pattern> [IN <source-path-prefix>] WITH (MATERIALS|PRODUCTS) 25 [IN <destination-path-prefix>] FROM <step>, 26 CREATE <pattern>, 27 DELETE <pattern>, 28 MODIFY <pattern>, 29 ALLOW <pattern>, 30 DISALLOW <pattern> 31 32 Rule tokens are normalized to lower case before returning. The returned map 33 has the following format: 34 35 { 36 "type": "match" | "create" | "delete" |"modify" | "allow" | "disallow" 37 "pattern": "<file name pattern>", 38 "srcPrefix": "<path or empty string>", // MATCH rule only 39 "dstPrefix": "<path or empty string>", // MATCH rule only 40 "dstType": "materials" | "products">, // MATCH rule only 41 "dstName": "<step name>", // Match rule only 42 } 43 44 If the rule does not match any of the available formats the first return value 45 is nil and the second return value is the error. 46 */ 47 func UnpackRule(rule []string) (map[string]string, error) { 48 // Cache rule len 49 ruleLen := len(rule) 50 51 // Create all lower rule copy to case-insensitively parse out tokens whose 52 // position we don't know yet. We keep the original rule to retain the 53 // non-token elements' case. 54 ruleLower := make([]string, ruleLen) 55 for i, val := range rule { 56 ruleLower[i] = strings.ToLower(val) 57 } 58 59 switch ruleLower[0] { 60 case "create", "modify", "delete", "allow", "disallow", "require": 61 if ruleLen != 2 { 62 return nil, 63 fmt.Errorf("%s Got:\n\t %s", errorMsg, rule) 64 } 65 66 return map[string]string{ 67 "type": ruleLower[0], 68 "pattern": rule[1], 69 }, nil 70 71 case "match": 72 var srcPrefix string 73 var dstType string 74 var dstPrefix string 75 var dstName string 76 77 // MATCH <pattern> IN <source-path-prefix> WITH (MATERIALS|PRODUCTS) \ 78 // IN <destination-path-prefix> FROM <step> 79 if ruleLen == 10 && ruleLower[2] == "in" && 80 ruleLower[4] == "with" && ruleLower[6] == "in" && 81 ruleLower[8] == "from" { 82 srcPrefix = rule[3] 83 dstType = ruleLower[5] 84 dstPrefix = rule[7] 85 dstName = rule[9] 86 // MATCH <pattern> IN <source-path-prefix> WITH (MATERIALS|PRODUCTS) \ 87 // FROM <step> 88 } else if ruleLen == 8 && ruleLower[2] == "in" && 89 ruleLower[4] == "with" && ruleLower[6] == "from" { 90 srcPrefix = rule[3] 91 dstType = ruleLower[5] 92 dstPrefix = "" 93 dstName = rule[7] 94 95 // MATCH <pattern> WITH (MATERIALS|PRODUCTS) IN <destination-path-prefix> 96 // FROM <step> 97 } else if ruleLen == 8 && ruleLower[2] == "with" && 98 ruleLower[4] == "in" && ruleLower[6] == "from" { 99 srcPrefix = "" 100 dstType = ruleLower[3] 101 dstPrefix = rule[5] 102 dstName = rule[7] 103 104 // MATCH <pattern> WITH (MATERIALS|PRODUCTS) FROM <step> 105 } else if ruleLen == 6 && ruleLower[2] == "with" && 106 ruleLower[4] == "from" { 107 srcPrefix = "" 108 dstType = ruleLower[3] 109 dstPrefix = "" 110 dstName = rule[5] 111 112 } else { 113 return nil, 114 fmt.Errorf("%s Got:\n\t %s", errorMsg, rule) 115 116 } 117 118 return map[string]string{ 119 "type": ruleLower[0], 120 "pattern": rule[1], 121 "srcPrefix": srcPrefix, 122 "dstPrefix": dstPrefix, 123 "dstType": dstType, 124 "dstName": dstName, 125 }, nil 126 127 default: 128 return nil, 129 fmt.Errorf("%s Got:\n\t %s", errorMsg, rule) 130 } 131 }