package main import ( "fmt" "net/url" ) // config accepts a slice of type Redirect and returns an error // it organizes the input data in a way that makes sense for FortiOS objects // then outputs the configuration to stdout func config(redirects []Redirect) error { // A map which contains the name of a redirect policy as the key, and a slice of strings as a value. // The value of the string is the name of the url-rewrite-rule which needs to be referenced by the redirect policy object in FortiOS redirectPolicies := make(map[string][]string) // Iterate over all redirects and output url-rewrite-rules fmt.Printf("\n\n------------------------ COPY BELOW THIS LINE ------------------------\n\n\n") fmt.Println("config waf url-rewrite url-rewrite-rule") for _, redirect := range redirects { // Parse the source URL string into a URL object so we can extract features sourceURL, err := url.Parse(redirect.sourceURL) if err != nil { return fmt.Errorf("unable to parse source URL '%s': %v", redirect.sourceURL, err) } var ruleName, action string if len(redirect.sourceURL) > 63 { // FortiOS only allows up to 63 characters. There is potention for collission here. TBD: Reduce and replace characters in the middle of string with '...' and show characters at the end of the URL to make differentiation easier for operators of the WAF ruleName = redirect.sourceURL[:62] } else { ruleName = redirect.sourceURL } if redirect.statusCode == 301 { //translate to fortiOS syntax action = "redirect-301" } else { action = "redirect" } // Output FortiOS configuration syntax fmt.Printf("edit \"%s\"\n", ruleName) fmt.Printf("set location %s\n", redirect.destinationURL) fmt.Printf("set action %s\n", action) fmt.Println("config match-condition") fmt.Println("edit 0") fmt.Println("set object http-url") fmt.Printf("set reg-exp %s$\n", sourceURL.Path) fmt.Println("set protocol-filter enable") fmt.Printf("set HTTP-protocol %s\n", sourceURL.Scheme) fmt.Println("next") fmt.Println("end") fmt.Println("next") // Add this rule to the slice inside the policy map. This is used to organize data for creating the url-rewrite-policy configuration below redirectPolicies[sourceURL.Host] = append(redirectPolicies[sourceURL.Host], ruleName) } fmt.Println("end") // Output url-rewrite-policy configuration. // Iterate over values in the policy map and output the policy configuration fmt.Println("config waf url-rewrite url-rewrite-policy") for policyName, policyRules := range redirectPolicies { fmt.Printf("edit \"%s-redirects\"\n", policyName) fmt.Println("config rule") for _, ruleName := range policyRules { fmt.Println("edit 0") fmt.Printf("set url-rewrite-rule-name %s\n", ruleName) fmt.Println("next") } fmt.Println("end") fmt.Println("next") } fmt.Printf("end\n\n\n") return nil }