github.com/kiali/kiali@v1.84.0/business/checkers/authorization/namespace_method_checker.go (about) 1 package authorization 2 3 import ( 4 "fmt" 5 "regexp" 6 "strings" 7 8 api_security_v1beta "istio.io/api/security/v1beta1" 9 security_v1beta "istio.io/client-go/pkg/apis/security/v1beta1" 10 11 "github.com/kiali/kiali/models" 12 "github.com/kiali/kiali/util/httputil" 13 ) 14 15 var methodMatcher = regexp.MustCompile(`^((\/[a-zA-Z\.]+)+)(\/[a-zA-Z]+)$`) 16 17 type NamespaceMethodChecker struct { 18 AuthorizationPolicy *security_v1beta.AuthorizationPolicy 19 Namespaces models.NamespaceNames 20 } 21 22 func (ap NamespaceMethodChecker) Check() ([]*models.IstioCheck, bool) { 23 checks, valid := make([]*models.IstioCheck, 0), true 24 25 for ruleIdx, rule := range ap.AuthorizationPolicy.Spec.Rules { 26 if rule == nil { 27 continue 28 } 29 if len(rule.From) > 0 { 30 toChecks, toValid := ap.validateFromField(ruleIdx, rule.From) 31 checks = append(checks, toChecks...) 32 valid = valid && toValid 33 } 34 if len(rule.To) > 0 { 35 fromChecks, fromValid := ap.validateToField(ruleIdx, rule.To) 36 checks = append(checks, fromChecks...) 37 valid = valid && fromValid 38 } 39 } 40 return checks, valid 41 } 42 43 func (ap NamespaceMethodChecker) validateFromField(ruleIdx int, from []*api_security_v1beta.Rule_From) ([]*models.IstioCheck, bool) { 44 if len(from) == 0 { 45 return nil, true 46 } 47 48 checks, valid := make([]*models.IstioCheck, 0, len(from)), true 49 for fromIdx, f := range from { 50 if f == nil { 51 continue 52 } 53 54 if f.Source == nil { 55 continue 56 } 57 58 if len(f.Source.Namespaces) == 0 { 59 continue 60 } 61 62 for i, n := range f.Source.Namespaces { 63 if !ap.Namespaces.Includes(n) { 64 valid = true 65 path := fmt.Sprintf("spec/rules[%d]/from[%d]/source/namespaces[%d]", ruleIdx, fromIdx, i) 66 validation := models.Build("authorizationpolicy.source.namespacenotfound", path) 67 checks = append(checks, &validation) 68 } 69 } 70 } 71 72 return checks, valid 73 } 74 75 func (ap NamespaceMethodChecker) validateToField(ruleIdx int, to []*api_security_v1beta.Rule_To) ([]*models.IstioCheck, bool) { 76 if len(to) == 0 { 77 return nil, true 78 } 79 80 checks, valid := make([]*models.IstioCheck, 0, len(to)), true 81 for toIdx, t := range to { 82 if t == nil { 83 continue 84 } 85 86 if t.Operation == nil { 87 continue 88 } 89 90 if len(t.Operation.Methods) == 0 { 91 continue 92 } 93 94 for i, m := range t.Operation.Methods { 95 if !validMethod(m) { 96 valid = true 97 path := fmt.Sprintf("spec/rules[%d]/to[%d]/operation/methods[%d]", ruleIdx, toIdx, i) 98 validation := models.Build("authorizationpolicy.to.wrongmethod", path) 99 checks = append(checks, &validation) 100 } 101 } 102 } 103 104 return checks, valid 105 } 106 107 func validMethod(m string) bool { 108 valid := false 109 110 for _, httpMethod := range httputil.HttpMethods() { 111 // HTTP methods allowed or 112 // For gRPC service, a fully-qualified name like “/package.service/method” 113 valid = valid || (strings.TrimSpace(strings.ToUpper(m)) == httpMethod || methodMatcher.MatchString(m)) 114 } 115 116 return valid 117 }