Skip to content

Commit

Permalink
[release]Indexable sslVerifyNone
Browse files Browse the repository at this point in the history
Starting from this release,  field can be indexed. Fixes #443.
  • Loading branch information
vfarcic committed Mar 4, 2018
1 parent ec57095 commit 0ee0a76
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 28 deletions.
2 changes: 1 addition & 1 deletion actions/reconfigure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ backend https-myService-be1234_32
func (s ReconfigureTestSuite) Test_GetTemplates_AddSllVerifyNone_WhenSslVerifyNoneIsSet() {
s.reconfigure.Service.ServiceDest[0].Port = "1234"
s.reconfigure.Service.ServiceDest[0].Index = 6
s.reconfigure.SslVerifyNone = true
s.reconfigure.Service.ServiceDest[0].SslVerifyNone = true
expected := `
backend myService-be1234_6
mode http
Expand Down
6 changes: 3 additions & 3 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The following query parameters can be used to send a *reconfigure* request to *D
|timeoutTunnel |The tunnel timeout in seconds.<br>**Default:** `3600`<br>**Example:** `3600`|
|userDef |User defined value. This value is not used with current template. It is designed as a way to provide additional data that can be used with **custom templates**. The parameter must be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `userDef.1`, `userDef.2`, and so on).|

Multiple destinations for a single service can be specified by adding index as a suffix to `servicePath`, `servicePathExclude`, `srcPort`, `port`, `userAgent`, `ignoreAuthorization`, `serviceDomain`, `allowedMethods`, `deniedMethods`, `denyHttp`, `httpsOnly`, `redirectFromDomain`, `reqMode`, `reqPathSearchReplace`, `outboundHostname`, or `userDef` parameters. In that case, `srcPort` is required.
Multiple destinations for a single service can be specified by adding index as a suffix to `servicePath`, `servicePathExclude`, `srcPort`, `port`, `userAgent`, `ignoreAuthorization`, `serviceDomain`, `allowedMethods`, `deniedMethods`, `denyHttp`, `httpsOnly`, `redirectFromDomain`, `reqMode`, `reqPathSearchReplace`, `outboundHostname`, `sslVerifyNone`, or `userDef` parameters. In that case, `srcPort` is required.

### HTTP Mode Query Parameters

Expand All @@ -64,7 +64,7 @@ The following query parameters can be used only when `reqMode` is set to `http`
|servicePath |The URL path of the service. Multiple values should be separated with comma (`,`). The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `servicePath.1`, `servicePath.2`, and so on). This parameter **is mandatory** unless `serviceDomain` is specified.<br>**Example:** `/api/v1/books`|
|servicePathExclude|The URL path that should be excluded from the rules. Multiple values should be separated with comma (`,`). The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `servicePathExclude.1`, `servicePathExclude.2`, and so on).<br>**Example:** `/metrics`|
|sessionType |Determines the type of sticky sessions. If set to `sticky-server`, session cookie will be set by the proxy. Any other value means that sticky sessions are not used and load balancing is performed by Docker's Overlay network.<br>**Example:** `sticky-server`|
|sslVerifyNone|If set to true, backend server certificates are not verified. This flag should be set for SSL enabled backend services.<br>**Example:** `true`<br>**Default Value:** `false`|
|sslVerifyNone|If set to true, backend server certificates are not verified. This flag should be set for SSL enabled backend services. The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `sslVerifyNone.1`, `sslVerifyNone.2`, and so on).<br>**Example:** `true`<br>**Default Value:** `false`|
|templateBePath|The path to the template representing a snippet of the backend configuration. If specified, the backend template will be loaded from the specified file. See the [Templates](#templates) section for more info.<br>**Example:** `/tmpl/be.tmpl`|
|templateFePath|The path to the template representing a snippet of the frontend configuration. If specified, the frontend template will be loaded from the specified file. See the [Templates](#templates) section for more info.<br>**Example:** `/tmpl/fe.tmpl`|
|userAgent |A comma-separated list of user agents. only requests with the same User-Agent will be forwarded to the backend. The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `userAgent.1`, `userAgent.2`, and so on). If the same service is used for multiple agents, it is recommended to use indexes with the last one being without `userAgent`. That way, if no match is found, the last indexed destination will be used as catch-all.<br>**Example:** `googlebot,iphone`|
Expand All @@ -73,7 +73,7 @@ The following query parameters can be used only when `reqMode` is set to `http`
|usersPassEncrypted|Indicates whether passwords provided by `users` or `usersSecret` contain encrypted data. Passwords can be encrypted with the command `mkpasswd -m sha-512 password1`.<br>**Example:** `true`<br>**Default Value:** `false`|
|verifyClientSsl|Whether to verify client SSL and, if it is not valid, deny request and return 403 Forbidden status code. SSL is validated against the `ca-file` specified through the environment variable `CA_FILE`.<br>**Example:** true<br>**Default Value:** `false`|

Multiple destinations for a single service can be specified by adding index as a suffix to `servicePath`, `servicePathExclude`, `srcPort`, `port`, `userAgent`, `ignoreAuthorization`, `serviceDomain`, `allowedMethods`, `deniedMethods`, `denyHttp`, `httpsOnly`, `redirectFromDomain`, `ReqMode`, `reqPathSearchReplace`, `outboundHostname`, or `userDef` parameters. In that case, `srcPort` is required.
Multiple destinations for a single service can be specified by adding index as a suffix to `servicePath`, `servicePathExclude`, `srcPort`, `port`, `userAgent`, `ignoreAuthorization`, `serviceDomain`, `allowedMethods`, `deniedMethods`, `denyHttp`, `httpsOnly`, `redirectFromDomain`, `ReqMode`, `reqPathSearchReplace`, `outboundHostname`, `sslVerifyNone`, or `userDef` parameters. In that case, `srcPort` is required.

### TCP Mode HTTP Query Parameters

Expand Down
8 changes: 4 additions & 4 deletions proxy/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,10 @@ backend {{$.AclName}}-be{{.Port}}_{{.Index}}
cookie {{$.ServiceName}} insert indirect nocache
{{- end}}
{{- range $i, $t := $.Tasks}}
server {{$.ServiceName}}_{{$i}} {{$t}}:{{$sd.Port}} check cookie {{$.ServiceName}}_{{$i}}{{if eq $.SslVerifyNone true}} ssl verify none{{end}}
server {{$.ServiceName}}_{{$i}} {{$t}}:{{$sd.Port}} check cookie {{$.ServiceName}}_{{$i}}{{if eq $sd.SslVerifyNone true}} ssl verify none{{end}}
{{- end}}
{{- if not $.Tasks}}
server {{$.ServiceName}} {{if eq $sd.OutboundHostname ""}}{{$.ServiceName}}{{end}}{{if ne $sd.OutboundHostname ""}}{{$sd.OutboundHostname}}{{end}}:{{$sd.Port}}{{if eq $.CheckResolvers true}} check resolvers docker{{end}}{{if eq $.SslVerifyNone true}} ssl verify none{{end}}
server {{$.ServiceName}} {{if eq $sd.OutboundHostname ""}}{{$.ServiceName}}{{end}}{{if ne $sd.OutboundHostname ""}}{{$sd.OutboundHostname}}{{end}}:{{$sd.Port}}{{if eq $.CheckResolvers true}} check resolvers docker{{end}}{{if eq $sd.SslVerifyNone true}} ssl verify none{{end}}
{{- end}}
{{- if not .IgnoreAuthorization}}
{{- if and ($.Users) (not .IgnoreAuthorization)}}
Expand Down Expand Up @@ -235,10 +235,10 @@ backend https-{{$.AclName}}-be{{.Port}}_{{.Index}}
cookie {{$.ServiceName}} insert indirect nocache
{{- end}}
{{- range $i, $t := $.Tasks}}
server {{$.ServiceName}}_{{$i}} {{$t}}:{{$.HttpsPort}} check cookie {{$.ServiceName}}_{{$i}}{{if eq $.SslVerifyNone true}} ssl verify none{{end}}
server {{$.ServiceName}}_{{$i}} {{$t}}:{{$.HttpsPort}} check cookie {{$.ServiceName}}_{{$i}}{{if eq $sd.SslVerifyNone true}} ssl verify none{{end}}
{{- end}}
{{- if not $.Tasks}}
server {{$.ServiceName}} {{if eq $sd.OutboundHostname ""}}{{$.ServiceName}}{{end}}{{if ne $sd.OutboundHostname ""}}{{$sd.OutboundHostname}}{{end}}:{{$.HttpsPort}}{{if eq $.CheckResolvers true}} check resolvers docker{{end}}{{if eq $.SslVerifyNone true}} ssl verify none{{end}}
server {{$.ServiceName}} {{if eq $sd.OutboundHostname ""}}{{$.ServiceName}}{{end}}{{if ne $sd.OutboundHostname ""}}{{$sd.OutboundHostname}}{{end}}:{{$.HttpsPort}}{{if eq $.CheckResolvers true}} check resolvers docker{{end}}{{if eq $sd.SslVerifyNone true}} ssl verify none{{end}}
{{- end}}
{{- if not .IgnoreAuthorization}}
{{- if $.Users}}
Expand Down
22 changes: 13 additions & 9 deletions proxy/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ type ServiceDest struct {
SrcPortAcl string
// Internal use only. Do not modify.
SrcPortAclName string
// If set to true, server certificates are not verified. This flag should be set for SSL enabled backend services.
SslVerifyNone bool
// Whether to verify client SSL and deny request when it is invalid
VerifyClientSsl bool
// If specified, only requests with the same agent will be forwarded to the backend.
Expand Down Expand Up @@ -149,8 +151,6 @@ type Service struct {
SetReqHeader []string `split_words:"true"`
// Additional headers that will be set to the response before forwarding it to the client. If a specified header exists, it will be replaced with the new one.
SetResHeader []string `split_words:"true"`
// If set to true, server certificates are not verified. This flag should be set for SSL enabled backend services.
SslVerifyNone bool `split_words:"true"`
// The path to the template representing a snippet of the backend configuration.
// If specified, the backend template will be loaded from the specified file.
// If specified, `templateFePath` must be set as well.
Expand Down Expand Up @@ -325,7 +325,7 @@ func GetServiceFromProvider(provider ServiceParameterProvider) *Service {
sr.ServiceName,
provider.GetString("users"),
provider.GetString("usersSecret"),
getBoolParam(provider, "usersPassEncrypted"),
getBoolParam(provider, "usersPassEncrypted", ""),
globalUsersString,
globalUsersEncrypted,
)
Expand Down Expand Up @@ -430,10 +430,10 @@ func getServiceDest(sr *Service, provider ServiceParameterProvider, index int) S
return ServiceDest{
AllowedMethods: getSliceFromString(provider, fmt.Sprintf("allowedMethods%s", suffix)),
DeniedMethods: getSliceFromString(provider, fmt.Sprintf("deniedMethods%s", suffix)),
DenyHttp: getBoolParam(provider, fmt.Sprintf("denyHttp%s", suffix)),
HttpsOnly: getBoolParam(provider, fmt.Sprintf("httpsOnly%s", suffix)),
DenyHttp: getBoolParam(provider, "denyHttp", suffix),
HttpsOnly: getBoolParam(provider, "httpsOnly", suffix),
HttpsRedirectCode: provider.GetString(fmt.Sprintf("httpsRedirectCode%s", suffix)),
IgnoreAuthorization: getBoolParam(provider, fmt.Sprintf("ignoreAuthorization%s", suffix)),
IgnoreAuthorization: getBoolParam(provider, "ignoreAuthorization", suffix),
OutboundHostname: outboundHostname,
Port: provider.GetString(fmt.Sprintf("port%s", suffix)),
RedirectFromDomain: getSliceFromString(provider, fmt.Sprintf("redirectFromDomain%s", suffix)),
Expand All @@ -445,7 +445,8 @@ func getServiceDest(sr *Service, provider ServiceParameterProvider, index int) S
ServicePath: getSliceFromString(provider, fmt.Sprintf("servicePath%s", suffix)),
ServicePathExclude: getSliceFromString(provider, fmt.Sprintf("servicePathExclude%s", suffix)),
SrcPort: srcPort,
VerifyClientSsl: getBoolParam(provider, fmt.Sprintf("verifyClientSsl%s", suffix)),
SslVerifyNone: getBoolParam(provider, "sslVerifyNone", suffix),
VerifyClientSsl: getBoolParam(provider, "verifyClientSsl", suffix),
UserAgent: userAgent,
UserDef: provider.GetString(fmt.Sprintf("userDef%s", suffix)),
Index: sdIndex,
Expand All @@ -465,9 +466,12 @@ func isServiceDestValid(sd *ServiceDest) bool {
return len(sd.ServicePath) > 0 || len(sd.Port) > 0
}

func getBoolParam(req ServiceParameterProvider, param string) bool {
func getBoolParam(req ServiceParameterProvider, param, index string) bool {
value := false
if len(req.GetString(param)) > 0 {
key := fmt.Sprintf("%s%s", param, index)
if len(req.GetString(key)) > 0 {
value, _ = strconv.ParseBool(req.GetString(key))
} else if len(req.GetString(param)) > 0 {
value, _ = strconv.ParseBool(req.GetString(param))
}
return value
Expand Down
22 changes: 17 additions & 5 deletions proxy/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,18 @@ func (s *TypesTestSuite) Test_GetServiceFromProvider_ReturnsProxyServiceWithInde
s.Equal(expected, *actual)
}

func (s *TypesTestSuite) Test_GetServiceFromProvider_UsesDefaultValues_WhenBoolIndexIsNotPresent() {
expected := s.getExpectedService()
serviceMap := s.getServiceMap(expected, ".1", ",")
delete(serviceMap, "sslVerifyNone.1")
serviceMap["sslVerifyNone"] = "true"
provider := mapParameterProvider{&serviceMap}

actual := GetServiceFromProvider(&provider)

s.Equal(expected, *actual)
}

func (s *TypesTestSuite) Test_GetServiceFromProvider_UsesSeparatorFromEnvVar() {
separatorOrig := os.Getenv("SEPARATOR")
defer func() { os.Setenv("SEPARATOR", separatorOrig) }()
Expand Down Expand Up @@ -374,7 +386,6 @@ func (s *TypesTestSuite) getServiceMap(expected Service, indexSuffix, separator
"sessionType": expected.SessionType,
"setReqHeader": strings.Join(expected.SetReqHeader, separator),
"setResHeader": strings.Join(expected.SetResHeader, separator),
"sslVerifyNone": strconv.FormatBool(expected.SslVerifyNone),
"templateBePath": expected.TemplateBePath,
"templateFePath": expected.TemplateFePath,
"timeoutServer": expected.TimeoutServer,
Expand All @@ -396,6 +407,7 @@ func (s *TypesTestSuite) getServiceMap(expected Service, indexSuffix, separator
"serviceDomain" + indexSuffix: strings.Join(expected.ServiceDest[0].ServiceDomain, separator),
"serviceHeader" + indexSuffix: header,
"servicePath" + indexSuffix: strings.Join(expected.ServiceDest[0].ServicePath, separator),
"sslVerifyNone" + indexSuffix: strconv.FormatBool(expected.ServiceDest[0].SslVerifyNone),
"userAgent" + indexSuffix: strings.Join(expected.ServiceDest[0].UserAgent.Value, separator),
"userDef" + indexSuffix: expected.ServiceDest[0].UserDef,
"verifyClientSsl" + indexSuffix: strconv.FormatBool(expected.ServiceDest[0].VerifyClientSsl),
Expand Down Expand Up @@ -429,13 +441,14 @@ func (s *TypesTestSuite) getExpectedService() Service {
OutboundHostname: "outboundHostname",
Port: "1234",
RedirectFromDomain: []string{"sub.domain1", "sub.domain2"},
ReqMode: "reqMode",
ReqPathSearchReplace: "something,else:foo,bar",
ReqPathSearchReplaceFormatted: []string{"reqPathSearch,reqPathReplace", "something,else", "foo,bar"},
ServiceDomain: []string{"domain1", "domain2"},
ServiceHeader: map[string]string{"X-Version": "3", "name": "Viktor"},
ServicePath: []string{"/"},
ServicePathExclude: []string{},
ReqMode: "reqMode",
ReqPathSearchReplace: "something,else:foo,bar",
ReqPathSearchReplaceFormatted: []string{"reqPathSearch,reqPathReplace", "something,else", "foo,bar"},
SslVerifyNone: true,
UserAgent: UserAgent{Value: []string{"agent-1", "agent-2/replace-with_"}, AclName: "agent_1_agent_2_replace_with_"},
UserDef: "userDef",
VerifyClientSsl: true,
Expand All @@ -444,7 +457,6 @@ func (s *TypesTestSuite) getExpectedService() Service {
ServiceName: "serviceName",
SetReqHeader: []string{"set-header-1", "set-header-2"},
SetResHeader: []string{"set-header-1", "set-header-2"},
SslVerifyNone: true,
TemplateBePath: "templateBePath",
TemplateFePath: "templateFePath",
TimeoutServer: "timeoutServer",
Expand Down
2 changes: 2 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ func (m *serve) getServiceFromEnvVars(prefix string) (proxy.Service, error) {
verifyClientSsl, _ := strconv.ParseBool(os.Getenv(prefix + "_VERIFY_CLIENT_SSL"))
denyHTTP, _ := strconv.ParseBool(os.Getenv(prefix + "_DENY_HTTP"))
ignoreAuthorization, _ := strconv.ParseBool(os.Getenv(prefix + "_IGNORE_AUTHORIZATION"))
sslVerifyNone, _ := strconv.ParseBool(os.Getenv(prefix + "_SSL_VERIFY_NONE"))

if len(path) > 0 || len(port) > 0 {
sd = append(
Expand All @@ -291,6 +292,7 @@ func (m *serve) getServiceFromEnvVars(prefix string) (proxy.Service, error) {
ServicePath: path,
ServicePathExclude: servicePathExclude,
SrcPort: srcPort,
SslVerifyNone: sslVerifyNone,
VerifyClientSsl: verifyClientSsl,
},
)
Expand Down
11 changes: 5 additions & 6 deletions server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,12 +547,12 @@ func (s *ServerTestSuite) Test_GetServiceFromUrl_ReturnsProxyService() {
ServiceHeader: map[string]string{"X-Version": "3", "name": "Viktor"},
ServicePath: []string{"/"},
ServicePathExclude: []string{"/excluded-path"},
SslVerifyNone: true,
}},
ServiceDomainAlgo: "hdr_dom",
ServiceName: "serviceName",
SetReqHeader: []string{"set-header-1", "set-header-2"},
SetResHeader: []string{"set-header-1", "set-header-2"},
SslVerifyNone: true,
TemplateBePath: "templateBePath",
TemplateFePath: "templateFePath",
TimeoutServer: "timeoutServer",
Expand Down Expand Up @@ -585,7 +585,7 @@ func (s *ServerTestSuite) Test_GetServiceFromUrl_ReturnsProxyService() {
strings.Join(expected.ServiceDest[0].ServiceDomain, ","),
strings.Join(expected.ServiceDest[0].RedirectFromDomain, ","),
expected.Distribute,
expected.SslVerifyNone,
expected.ServiceDest[0].SslVerifyNone,
expected.ServiceDomainAlgo,
strings.Join(expected.AddReqHeader, ","),
strings.Join(expected.AddResHeader, ","),
Expand All @@ -600,7 +600,6 @@ func (s *ServerTestSuite) Test_GetServiceFromUrl_ReturnsProxyService() {
)
req, _ := http.NewRequest("GET", addr, nil)
srv := serve{}

actual := srv.GetServiceFromUrl(req)

s.Equal(expected, *actual)
Expand Down Expand Up @@ -679,7 +678,6 @@ func (s *ServerTestSuite) Test_GetServicesFromEnvVars_ReturnsServices() {
ServiceName: "my-ServiceName",
SetReqHeader: []string{"set-header-1", "set-header-2"},
SetResHeader: []string{"set-header-1", "set-header-2"},
SslVerifyNone: true,
TemplateBePath: "my-TemplateBePath",
TemplateFePath: "my-TemplateFePath",
TimeoutServer: "my-TimeoutServer",
Expand All @@ -688,6 +686,7 @@ func (s *ServerTestSuite) Test_GetServicesFromEnvVars_ReturnsServices() {
{
HttpsOnly: true,
HttpsRedirectCode: "302",
IgnoreAuthorization: true,
OutboundHostname: "my-OutboundHostname",
Port: "1111",
ReqPathSearchReplace: "/something,/else:/this,/that",
Expand All @@ -702,7 +701,7 @@ func (s *ServerTestSuite) Test_GetServicesFromEnvVars_ReturnsServices() {
ServicePathExclude: []string{"some-path", "some-path2"},
VerifyClientSsl: true,
DenyHttp: true,
IgnoreAuthorization: true,
SslVerifyNone: true,
},
},
}
Expand Down Expand Up @@ -734,7 +733,7 @@ func (s *ServerTestSuite) Test_GetServicesFromEnvVars_ReturnsServices() {
os.Setenv("DFP_SERVICE_SERVICE_DOMAIN_ALGO", service.ServiceDomainAlgo)
os.Setenv("DFP_SERVICE_SERVICE_NAME", service.ServiceName)
os.Setenv("DFP_SERVICE_SERVICE_PATH_EXCLUDE", strings.Join(service.ServiceDest[0].ServicePathExclude, ","))
os.Setenv("DFP_SERVICE_SSL_VERIFY_NONE", strconv.FormatBool(service.SslVerifyNone))
os.Setenv("DFP_SERVICE_SSL_VERIFY_NONE", strconv.FormatBool(service.ServiceDest[0].SslVerifyNone))
os.Setenv("DFP_SERVICE_TEMPLATE_BE_PATH", service.TemplateBePath)
os.Setenv("DFP_SERVICE_TEMPLATE_FE_PATH", service.TemplateFePath)
os.Setenv("DFP_SERVICE_TIMEOUT_SERVER", service.TimeoutServer)
Expand Down

0 comments on commit 0ee0a76

Please sign in to comment.