github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/k8s/appprotect/app_protect_resources.go (about) 1 package appprotect 2 3 import ( 4 "fmt" 5 "net" 6 "regexp" 7 "strconv" 8 "strings" 9 10 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 11 ) 12 13 var appProtectPolicyRequiredFields = [][]string{ 14 {"spec", "policy"}, 15 } 16 17 var appProtectLogConfRequiredFields = [][]string{ 18 {"spec", "content"}, 19 {"spec", "filter"}, 20 } 21 22 var appProtectUserSigRequiredSlices = [][]string{ 23 {"spec", "signatures"}, 24 } 25 26 func validateRequiredFields(obj *unstructured.Unstructured, fieldsList [][]string) error { 27 for _, fields := range fieldsList { 28 field, found, err := unstructured.NestedMap(obj.Object, fields...) 29 if err != nil { 30 return fmt.Errorf("Error checking for required field %v: %w", field, err) 31 } 32 if !found { 33 return fmt.Errorf("Required field %v not found", field) 34 } 35 } 36 return nil 37 } 38 39 func validateRequiredSlices(obj *unstructured.Unstructured, fieldsList [][]string) error { 40 for _, fields := range fieldsList { 41 field, found, err := unstructured.NestedSlice(obj.Object, fields...) 42 if err != nil { 43 return fmt.Errorf("Error checking for required field %v: %w", field, err) 44 } 45 if !found { 46 return fmt.Errorf("Required field %v not found", field) 47 } 48 } 49 return nil 50 } 51 52 // validateAppProtectPolicy validates Policy resource 53 func validateAppProtectPolicy(policy *unstructured.Unstructured) error { 54 polName := policy.GetName() 55 56 err := validateRequiredFields(policy, appProtectPolicyRequiredFields) 57 if err != nil { 58 return fmt.Errorf("Error validating App Protect Policy %v: %w", polName, err) 59 } 60 61 return nil 62 } 63 64 // validateAppProtectLogConf validates LogConfiguration resource 65 func validateAppProtectLogConf(logConf *unstructured.Unstructured) error { 66 lcName := logConf.GetName() 67 err := validateRequiredFields(logConf, appProtectLogConfRequiredFields) 68 if err != nil { 69 return fmt.Errorf("Error validating App Protect Log Configuration %v: %w", lcName, err) 70 } 71 72 return nil 73 } 74 75 var ( 76 logDstEx = regexp.MustCompile(`(?:syslog:server=((?:\d{1,3}\.){3}\d{1,3}|localhost):\d{1,5})|stderr|(?:\/[\S]+)+`) 77 logDstFileEx = regexp.MustCompile(`(?:\/[\S]+)+`) 78 ) 79 80 // ValidateAppProtectLogDestination validates destination for log configuration 81 func ValidateAppProtectLogDestination(dstAntn string) error { 82 errormsg := "Error parsing App Protect Log config: Destination must follow format: syslog:server=<ip-address | localhost>:<port> or stderr or absolute path to file" 83 if !logDstEx.MatchString(dstAntn) { 84 return fmt.Errorf("%s Log Destination did not follow format", errormsg) 85 } 86 if dstAntn == "stderr" { 87 return nil 88 } 89 90 if logDstFileEx.MatchString(dstAntn) { 91 return nil 92 } 93 94 dstchunks := strings.Split(dstAntn, ":") 95 96 // This error can be ignored since the regex check ensures this string will be parsable 97 port, _ := strconv.Atoi(dstchunks[2]) 98 99 if port > 65535 || port < 1 { 100 return fmt.Errorf("Error parsing port: %v not a valid port number", port) 101 } 102 103 ipstr := strings.Split(dstchunks[1], "=")[1] 104 if ipstr == "localhost" { 105 return nil 106 } 107 108 if net.ParseIP(ipstr) == nil { 109 return fmt.Errorf("Error parsing host: %v is not a valid ip address", ipstr) 110 } 111 112 return nil 113 } 114 115 // ParseResourceReferenceAnnotation returns a namespace/name string 116 func ParseResourceReferenceAnnotation(ns, antn string) string { 117 if !strings.Contains(antn, "/") { 118 return ns + "/" + antn 119 } 120 return antn 121 } 122 123 // ParseResourceReferenceAnnotationList returns a slice of ns/names strings 124 func ParseResourceReferenceAnnotationList(ns, annotations string) []string { 125 var out []string 126 for _, antn := range strings.Split(annotations, ",") { 127 out = append(out, ParseResourceReferenceAnnotation(ns, antn)) 128 } 129 return out 130 } 131 132 func validateAppProtectUserSig(userSig *unstructured.Unstructured) error { 133 sigName := userSig.GetName() 134 err := validateRequiredSlices(userSig, appProtectUserSigRequiredSlices) 135 if err != nil { 136 return fmt.Errorf("Error validating App Protect User Signature %v: %w", sigName, err) 137 } 138 139 return nil 140 } 141 142 // GetNsName gets the key of a resource in the format: "resNamespace/resName" 143 func GetNsName(obj *unstructured.Unstructured) string { 144 return obj.GetNamespace() + "/" + obj.GetName() 145 }