From 9598f646f516e8e650c51d48435154a92f0a91c9 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 13 Oct 2017 15:04:02 +0200 Subject: [PATCH] New entry point parser. --- configuration/configuration.go | 66 ++++++++++++------------- configuration/configuration_test.go | 74 +++++++++++++++++++---------- 2 files changed, 82 insertions(+), 58 deletions(-) diff --git a/configuration/configuration.go b/configuration/configuration.go index b112af7e6..7e489a008 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -5,7 +5,6 @@ import ( "fmt" "io/ioutil" "os" - "regexp" "strings" "time" @@ -193,55 +192,52 @@ func (ep *EntryPoints) String() string { // Set's argument is a string to be parsed to set the flag. // It's a comma-separated list, so we split it. func (ep *EntryPoints) Set(value string) error { - result, err := parseEntryPointsConfiguration(value) - if err != nil { - return err - } + result := parseEntryPointsConfiguration(value) var configTLS *TLS - if len(result["TLS"]) > 0 { + if len(result["tls"]) > 0 { certs := Certificates{} - if err := certs.Set(result["TLS"]); err != nil { + if err := certs.Set(result["tls"]); err != nil { return err } configTLS = &TLS{ Certificates: certs, } - } else if len(result["TLSACME"]) > 0 { + } else if len(result["tls_acme"]) > 0 { configTLS = &TLS{ Certificates: Certificates{}, } } - if len(result["CA"]) > 0 { - files := strings.Split(result["CA"], ",") + if len(result["ca"]) > 0 { + files := strings.Split(result["ca"], ",") configTLS.ClientCAFiles = files } var redirect *Redirect - if len(result["RedirectEntryPoint"]) > 0 || len(result["RedirectRegex"]) > 0 || len(result["RedirectReplacement"]) > 0 { + if len(result["redirect_entrypoint"]) > 0 || len(result["redirect_regex"]) > 0 || len(result["redirect_replacement"]) > 0 { redirect = &Redirect{ - EntryPoint: result["RedirectEntryPoint"], - Regex: result["RedirectRegex"], - Replacement: result["RedirectReplacement"], + EntryPoint: result["redirect_entrypoint"], + Regex: result["redirect_regex"], + Replacement: result["redirect_replacement"], } } whiteListSourceRange := []string{} - if len(result["WhiteListSourceRange"]) > 0 { - whiteListSourceRange = strings.Split(result["WhiteListSourceRange"], ",") + if len(result["whitelistsourcerange"]) > 0 { + whiteListSourceRange = strings.Split(result["whitelistsourcerange"], ",") } - compress := toBool(result, "Compress") + compress := toBool(result, "compress") var proxyProtocol *ProxyProtocol - if len(result["ProxyProtocol"]) > 0 { - trustedIPs := strings.Split(result["ProxyProtocol"], ",") + if len(result["proxyprotocol_trustedips"]) > 0 { + trustedIPs := strings.Split(result["proxyprotocol_trustedips"], ",") proxyProtocol = &ProxyProtocol{ TrustedIPs: trustedIPs, } } - (*ep)[result["Name"]] = &EntryPoint{ - Address: result["Address"], + (*ep)[result["name"]] = &EntryPoint{ + Address: result["address"], TLS: configTLS, Redirect: redirect, Compress: compress, @@ -252,20 +248,24 @@ func (ep *EntryPoints) Set(value string) error { return nil } -func parseEntryPointsConfiguration(value string) (map[string]string, error) { - regex := regexp.MustCompile(`(?:Name:(?P\S*))\s*(?:Address:(?P
\S*))?\s*(?:TLS:(?P\S*))?\s*(?PTLS)?\s*(?:CA:(?P\S*))?\s*(?:Redirect\.EntryPoint:(?P\S*))?\s*(?:Redirect\.Regex:(?P\S*))?\s*(?:Redirect\.Replacement:(?P\S*))?\s*(?:Compress:(?P\S*))?\s*(?:WhiteListSourceRange:(?P\S*))?\s*(?:ProxyProtocol\.TrustedIPs:(?P\S*))?`) - match := regex.FindAllStringSubmatch(value, -1) - if match == nil { - return nil, fmt.Errorf("bad EntryPoints format: %s", value) - } - matchResult := match[0] - result := make(map[string]string) - for i, name := range regex.SubexpNames() { - if i != 0 && len(matchResult[i]) != 0 { - result[name] = matchResult[i] +func parseEntryPointsConfiguration(raw string) map[string]string { + sections := strings.Fields(raw) + + config := make(map[string]string) + for _, part := range sections { + field := strings.SplitN(part, ":", 2) + name := strings.ToLower(strings.Replace(field[0], ".", "_", -1)) + if len(field) > 1 { + config[name] = field[1] + } else { + if strings.EqualFold(name, "TLS") { + config["tls_acme"] = "TLS" + } else { + config[name] = "" + } } } - return result, nil + return config } func toBool(conf map[string]string, key string) bool { diff --git a/configuration/configuration_test.go b/configuration/configuration_test.go index 591e32d91..5e7ac0ad7 100644 --- a/configuration/configuration_test.go +++ b/configuration/configuration_test.go @@ -16,36 +16,36 @@ func Test_parseEntryPointsConfiguration(t *testing.T) { }{ { name: "all parameters", - value: "Name:foo Address:bar TLS:goo TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:WhiteListSourceRange ProxyProtocol.TrustedIPs:192.168.0.1", + value: "Name:foo TLS:goo TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:WhiteListSourceRange ProxyProtocol.TrustedIPs:192.168.0.1 Address::8000", expectedResult: map[string]string{ - "Name": "foo", - "Address": "bar", - "CA": "car", - "TLS": "goo", - "TLSACME": "TLS", - "RedirectEntryPoint": "RedirectEntryPoint", - "RedirectRegex": "RedirectRegex", - "RedirectReplacement": "RedirectReplacement", - "WhiteListSourceRange": "WhiteListSourceRange", - "ProxyProtocol": "192.168.0.1", - "Compress": "true", + "name": "foo", + "address": ":8000", + "ca": "car", + "tls": "goo", + "tls_acme": "TLS", + "redirect_entrypoint": "RedirectEntryPoint", + "redirect_regex": "RedirectRegex", + "redirect_replacement": "RedirectReplacement", + "whitelistsourcerange": "WhiteListSourceRange", + "proxyprotocol_trustedips": "192.168.0.1", + "compress": "true", }, }, { name: "compress on", - value: "Name:foo Compress:on", + value: "name:foo Compress:on", expectedResult: map[string]string{ - "Name": "foo", - "Compress": "on", + "name": "foo", + "compress": "on", }, }, { name: "TLS", value: "Name:foo TLS:goo TLS", expectedResult: map[string]string{ - "Name": "foo", - "TLS": "goo", - "TLSACME": "TLS", + "name": "foo", + "tls": "goo", + "tls_acme": "TLS", }, }, } @@ -55,10 +55,7 @@ func Test_parseEntryPointsConfiguration(t *testing.T) { t.Run(test.name, func(t *testing.T) { t.Parallel() - conf, err := parseEntryPointsConfiguration(test.value) - if err != nil { - t.Error(err) - } + conf := parseEntryPointsConfiguration(test.value) for key, value := range conf { fmt.Println(key, value) @@ -133,11 +130,38 @@ func TestEntryPoints_Set(t *testing.T) { expectedEntryPoint *EntryPoint }{ { - name: "all parameters", - expression: "Name:foo Address:bar TLS:goo,gii TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:Range ProxyProtocol.TrustedIPs:192.168.0.1", + name: "all parameters camelcase", + expression: "Name:foo Address::8000 TLS:goo,gii TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:Range ProxyProtocol.TrustedIPs:192.168.0.1", expectedEntryPointName: "foo", expectedEntryPoint: &EntryPoint{ - Address: "bar", + Address: ":8000", + Redirect: &Redirect{ + EntryPoint: "RedirectEntryPoint", + Regex: "RedirectRegex", + Replacement: "RedirectReplacement", + }, + Compress: true, + ProxyProtocol: &ProxyProtocol{ + TrustedIPs: []string{"192.168.0.1"}, + }, + WhitelistSourceRange: []string{"Range"}, + TLS: &TLS{ + ClientCAFiles: []string{"car"}, + Certificates: Certificates{ + { + CertFile: FileOrContent("goo"), + KeyFile: FileOrContent("gii"), + }, + }, + }, + }, + }, + { + name: "all parameters lowercase", + expression: "name:foo address::8000 tls:goo,gii tls ca:car redirect.entryPoint:RedirectEntryPoint redirect.regex:RedirectRegex redirect.replacement:RedirectReplacement compress:true whiteListSourceRange:Range proxyProtocol.TrustedIPs:192.168.0.1", + expectedEntryPointName: "foo", + expectedEntryPoint: &EntryPoint{ + Address: ":8000", Redirect: &Redirect{ EntryPoint: "RedirectEntryPoint", Regex: "RedirectRegex",