2020-05-30 02:03:03 +00:00
package main
import (
"fmt"
"net/url"
)
// config accepts a slice of type Redirect and returns an error
2020-05-30 20:10:56 +00:00
// it organizes the input data in a way that makes sense for FortiOS objects
2020-05-30 02:03:03 +00:00
// 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.
2020-05-30 20:10:56 +00:00
// 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
2020-05-30 02:03:03 +00:00
redirectPolicies := make ( map [ string ] [ ] string )
// Iterate over all redirects and output url-rewrite-rules
2020-05-30 20:10:56 +00:00
fmt . Printf ( "\n\n------------------------ COPY BELOW THIS LINE ------------------------\n\n\n" )
2020-05-30 02:03:03 +00:00
fmt . Println ( "config waf url-rewrite url-rewrite-rule" )
for _ , redirect := range redirects {
2020-05-30 20:10:56 +00:00
// Parse the source URL string into a URL object so we can extract features
2020-05-30 02:03:03 +00:00
sourceURL , err := url . Parse ( redirect . sourceURL )
if err != nil {
2020-05-30 02:25:45 +00:00
return fmt . Errorf ( "unable to parse source URL '%s': %v" , redirect . sourceURL , err )
2020-05-30 02:03:03 +00:00
}
2020-05-30 03:00:52 +00:00
var ruleName , action string
2020-05-30 20:10:56 +00:00
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
2020-05-30 02:32:50 +00:00
ruleName = redirect . sourceURL [ : 62 ]
} else {
ruleName = redirect . sourceURL
}
2020-05-30 03:00:52 +00:00
if redirect . statusCode == 301 { //translate to fortiOS syntax
action = "redirect-301"
} else {
action = "redirect"
}
2020-05-30 20:10:56 +00:00
// Output FortiOS configuration syntax
2020-05-30 02:39:22 +00:00
fmt . Printf ( "edit \"%s\"\n" , ruleName )
2020-05-30 02:03:03 +00:00
fmt . Printf ( "set location %s\n" , redirect . destinationURL )
2020-05-30 03:00:52 +00:00
fmt . Printf ( "set action %s\n" , action )
2020-05-30 02:03:03 +00:00
fmt . Println ( "config match-condition" )
fmt . Println ( "edit 0" )
fmt . Println ( "set object http-url" )
2020-05-30 03:59:47 +00:00
fmt . Printf ( "set reg-exp %s$\n" , sourceURL . Path )
2020-05-30 02:03:03 +00:00
fmt . Println ( "set protocol-filter enable" )
fmt . Printf ( "set HTTP-protocol %s\n" , sourceURL . Scheme )
fmt . Println ( "next" )
fmt . Println ( "end" )
fmt . Println ( "next" )
2020-05-30 20:10:56 +00:00
// Add this rule to the slice inside the policy map. This is used to organize data for creating the url-rewrite-policy configuration below
2020-05-30 02:32:50 +00:00
redirectPolicies [ sourceURL . Host ] = append ( redirectPolicies [ sourceURL . Host ] , ruleName )
2020-05-30 02:03:03 +00:00
}
fmt . Println ( "end" )
2020-05-30 20:10:56 +00:00
// Output url-rewrite-policy configuration.
2020-05-30 02:03:03 +00:00
// 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 {
2020-05-30 02:44:53 +00:00
fmt . Printf ( "edit \"%s-redirects\"\n" , policyName )
2020-05-30 02:47:34 +00:00
fmt . Println ( "config rule" )
2020-05-30 02:03:03 +00:00
for _ , ruleName := range policyRules {
fmt . Println ( "edit 0" )
2020-05-30 02:44:53 +00:00
fmt . Printf ( "set url-rewrite-rule-name %s\n" , ruleName )
2020-05-30 02:03:03 +00:00
fmt . Println ( "next" )
}
2020-05-30 02:47:34 +00:00
fmt . Println ( "end" )
2020-05-30 02:03:03 +00:00
fmt . Println ( "next" )
}
2020-05-30 20:10:56 +00:00
fmt . Printf ( "end\n\n\n" )
2020-05-30 02:03:03 +00:00
return nil
}