Skip to content

Commit

Permalink
Fixes #333
Browse files Browse the repository at this point in the history
  • Loading branch information
vfarcic committed Sep 25, 2017
1 parent 0fe247f commit 1ad9856
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 42 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ ENV CERTS="" \
PROXY_INSTANCE_NAME="docker-flow" \
RELOAD_INTERVAL="5000" REPEAT_RELOAD=false \
RECONFIGURE_ATTEMPTS="20" \
SEPARATOR="," \
SERVICE_NAME="proxy" SERVICE_DOMAIN_ALGO="hdr(host)" \
STATS_USER="" STATS_USER_ENV="STATS_USER" STATS_PASS="" STATS_PASS_ENV="STATS_PASS" STATS_URI="" STATS_URI_ENV="STATS_URI" STATS_PORT="" \
TIMEOUT_HTTP_REQUEST="5" TIMEOUT_HTTP_KEEP_ALIVE="15" TIMEOUT_CLIENT="20" TIMEOUT_CONNECT="5" TIMEOUT_QUEUE="30" TIMEOUT_SERVER="20" TIMEOUT_TUNNEL="3600" \
Expand Down
1 change: 1 addition & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ PROXY_INSTANCE_NAME|The name of the proxy instance. Useful if multiple proxies a
|RELOAD_INTERVAL |Defines the frequency (in milliseconds) between automatic config reloads from Swarm Listener.<br>**Default value:** `5000`|
|REPEAT_RELOAD |If set to `true`, the proxy will periodically reload the config, using `RELOAD_INTERVAL` as pause between iterations.<br>**Example:** `true`<br>**Default value:** `false`|
|RECONFIGURE_ATTEMPTS|The number of attempts the proxy will try to reconfigure itself before giving up and removing the offending service. The period between reconfigure attempts is 1 second.<br>**Example:** `15`<br>**Default value:** `20`|
|SEPARATOR |The character used to separate multiple values.<br>**Default value:** `,` (comma)|
|SERVICE_DOMAIN_ALGO|The default algorithm applied to domain ACLs. It can be overwritten for a service through the `serviceDomainAlgo` parameter.<br>**Examples:**<br>`hdr(host)`: matches only if domain is the same as `serviceDomain`<br>`hdr_dom(host)`: matches the specified `serviceDomain` and any subdomain (a string either isolated or delimited by dots).<br>`req.ssl_sni`: matches Server Name TLS extension<br>**Default Value:** `hdr(host)`|
|SKIP_ADDRESS_VALIDATION|Whether to skip validating service address before reconfiguring the proxy.<br>**Example:** false<br>**Default value:** `true`|
|SSL_BIND_CIPHERS |Sets the default string describing the list of cipher algorithms ("cipher suite") that are negotiated during the SSL/TLS handshake for all "bind" lines which do not explicitly define theirs. The format of the string is defined in "man 1 ciphers" from OpenSSL man pages, and can be for instance a string such as `AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH`.<br>**Default value:** see [Dockerfile](https://github.com/vfarcic/docker-flow-proxy/blob/master/Dockerfile#L31)|
Expand Down
16 changes: 8 additions & 8 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ The following query parameters can be used to send a *reconfigure* request to *D
|Query |Description |
|---------------|------------------------------------------------------------------------------------------|
|aclName |ACLs are ordered alphabetically by their names. If not specified, serviceName is used instead.<br>**Example:** `05-go-demo-acl`|
|addReqHeader |Additional headers that will be added to the request before forwarding it to the service. Multiple headers should be separated with comma (`,`). Please consult [Add a header to the request](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#add-a-header-to-the-request) for more info.<br>**Example:** `X-Forwarded-Port %[dst_port],X-Forwarded-Ssl on if { ssl_fc }`|
|addResHeader |Additional headers that will be added to the response before forwarding it to the client. Multiple headers should be separated with comma (`,`). Please consult [Add a header to the response](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#rewriting-http-responses) for more info.<br>**Example:** `X-Via %[env(HOSTNAME)],Server haproxy`|
|addReqHeader |Additional headers that will be added to the request before forwarding it to the service. Multiple headers should be separated with comma (`,`). Change the environment variable `SEPARATOR` if comma is to be used for other purposes. Please consult [Add a header to the request](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#add-a-header-to-the-request) for more info.<br>**Example:** `X-Forwarded-Port %[dst_port],X-Forwarded-Ssl on if { ssl_fc }`|
|addResHeader |Additional headers that will be added to the response before forwarding it to the client. Multiple headers should be separated with comma (`,`). Change the environment variable `SEPARATOR` if comma is to be used for other purposes. Please consult [Add a header to the response](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#rewriting-http-responses) for more info.<br>**Example:** `X-Via %[env(HOSTNAME)],Server haproxy`|
|backendExtra |Additional configuration that will be added to the bottom of the service backend |
|connectionMode |HAProxy supports 5 connection modes.<br><br>`http-keep-alive`: all requests and responses are processed.<br>`http-tunnel`: only the first request and response are processed, everything else is forwarded with no analysis.<br>`httpclose`: tunnel with "Connection: close" added in both directions.<br>`http-server-close`: the server-facing connection is closed after the response.<br>`forceclose`: the connection is actively closed after end of response.<br><br>In general, it is preferred to use `http-server-close` with application servers, and some static servers might benefit from `http-keep-alive`.<br>Connection mode is restricted to HTTP mode only. If specified, connection mode will be applied to the backend section.<br>**Example:** http-keep-alive|
|delReqHeader |Additional headers that will be deleted in the request before forwarding it to the service. Multiple headers should be separated with comma (`,`). Please consult [Delete a header in the request](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#delete-a-header-in-the-request) for more info.<br>**Example:** `X-Forwarded-For,Cookie`|
|delResHeader |Additional headers that will be deleted in the response before forwarding it to the client. Multiple headers should be separated with comma (`,`). Please consult [Delete a header in the response](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#delete-a-header-in-the-response) for more info.<br>**Example:** `X-Varnish,X-Cache`|
|delReqHeader |Additional headers that will be deleted in the request before forwarding it to the service. Multiple headers should be separated with comma (`,`). Change the environment variable `SEPARATOR` if comma is to be used for other purposes. Please consult [Delete a header in the request](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#delete-a-header-in-the-request) for more info.<br>**Example:** `X-Forwarded-For,Cookie`|
|delResHeader |Additional headers that will be deleted in the response before forwarding it to the client. Multiple headers should be separated with comma (`,`). Change the environment variable `SEPARATOR` if comma is to be used for other purposes. Please consult [Delete a header in the response](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#delete-a-header-in-the-response) for more info.<br>**Example:** `X-Varnish,X-Cache`|
|distribute |Whether to distribute a request to all the instances of the proxy. Used only in the *swarm* mode.<br>**Example:** `true`|false|
|httpsPort |The internal HTTPS port of a service that should be reconfigured. The port is used only in the `swarm` mode. If not specified, the `port` parameter will be used instead.<br>**Example:** `443`|
|ignoreAuthorization|If set to true, the service destination will not require authorization. The parameter must be prefixed with the index of the service destion that should be excluded from authorization.<br>**Default:** `false`<br>**Example:** `true`|
Expand All @@ -30,8 +30,8 @@ The following query parameters can be used to send a *reconfigure* request to *D
|reqPathReplace |A regular expression to apply the modification.<br>**Example:** `/demo/`|
|reqPathSearch |A regular expression to search the content to be replaced. If specified, `reqPathReplace` needs to be set as well.<br>**Example:** `/something/`|
|serviceName |The name of the service. It must match the name of the Swarm service. This parameter is **mandatory**. If used through *Docker Flow Swarm Listener*, this parameter is added automatically.<br>**Example:** `go-demo`|
|setReqHeader |Additional headers that will be set to the request before forwarding it to the service. If a specified header exists, it will be replaced with the new one. Multiple headers should be separated with comma (`,`). Please consult [Set a header to the request](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#set-a-header-in-the-request) for more info.<br>**Example:** `X-Forwarded-Port %[dst_port],X-Forwarded-Ssl on if { ssl_fc }`|
|setResHeader |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. Multiple headers should be separated with comma (`,`). Please consult [Set a header to the response](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#set-a-header-in-the-response) for more info.<br>**Example:** `X-Via %[env(HOSTNAME)],Server haproxy`|
|setReqHeader |Additional headers that will be set to the request before forwarding it to the service. If a specified header exists, it will be replaced with the new one. Multiple headers should be separated with comma (`,`). Change the environment variable `SEPARATOR` if comma is to be used for other purposes. Please consult [Set a header to the request](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#set-a-header-in-the-request) for more info.<br>**Example:** `X-Forwarded-Port %[dst_port],X-Forwarded-Ssl on if { ssl_fc }`|
|setResHeader |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. Multiple headers should be separated with comma (`,`). Change the environment variable `SEPARATOR` if comma is to be used for other purposes. Please consult [Set a header to the response](https://www.haproxy.com/doc/aloha/7.0/haproxy/http_rewriting.html#set-a-header-in-the-response) for more info.<br>**Example:** `X-Via %[env(HOSTNAME)],Server haproxy`|
|srcPort |The source (entry) port of a service. The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `srcPort.1`, `srcPort.2`, and so on). The parameter is mandatory when specifying multiple destinations of a single service.<br>**Example:** `80`|
|timeoutServer |The server timeout in seconds.<br>**Default:** `20`<br>**Example:** `60`|
|timeoutTunnel |The tunnel timeout in seconds.<br>**Default:** `3600`<br>**Example:** `3600`|
Expand All @@ -45,8 +45,8 @@ The following query parameters can be used only when `reqMode` is set to `http`

|Query |Description |
|-------------|--------------------------------------------------------------------------------|
|allowedMethods|The list of allowed methods. If specified, a request with a method that is not on the list will be denied. Multiple methods can be separated with comma (`,`). The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `allowedMethods.1`, `allowedMethods.2`, and so on).<br>**Example:** `GET,DELETE`|
|deniedMethods|The list of denied methods. If specified, a request with a method that is on the list will be denied. Multiple methods can be separated with comma (`,`). The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `deniedMethods.1`, `deniedMethods.2`, and so on).<br>**Example:** `PUT,POST`|
|allowedMethods|The list of allowed methods. If specified, a request with a method that is not on the list will be denied. Multiple methods can be separated with comma (`,`). Change the environment variable `SEPARATOR` if comma is to be used for other purposes. The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `allowedMethods.1`, `allowedMethods.2`, and so on).<br>**Example:** `GET,DELETE`|
|deniedMethods|The list of denied methods. If specified, a request with a method that is on the list will be denied. Multiple methods can be separated with comma (`,`). Change the environment variable `SEPARATOR` if comma is to be used for other purposes. The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `deniedMethods.1`, `deniedMethods.2`, and so on).<br>**Example:** `PUT,POST`|
|denyHttp |Whether to deny HTTP requests thus allowing only HTTPS. The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `denyHttp.1`, `denyHttp.2`, and so on).<br>**Example:** `true`<br>**Default Value:** `false`|
|httpsOnly |If set to true, HTTP requests to the service will be redirected to HTTPS. The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `httpsOnly.1`, `httpsOnly.2`, and so on).<br>**Example:** `true`<br>**Default Value:** `false`|
|outboundHostname|The hostname where the service is running, for instance on a separate swarm. If specified, the proxy will dispatch requests to that domain.<br>**Example:** `ecme.com`|
Expand Down
26 changes: 15 additions & 11 deletions proxy/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"strconv"
"strings"
"os"
)

var usersBasePath string = "/run/secrets/dfp_users_%s"
Expand Down Expand Up @@ -264,6 +265,7 @@ func GetServiceFromMap(req *map[string]string) *Service {
func GetServiceFromProvider(provider ServiceParameterProvider) *Service {
sr := new(Service)
provider.Fill(sr)
separator := os.Getenv("SEPARATOR")
// TODO: Remove. It's added to maintain backwards compatibility with the deprecated parameter serviceDomainMatchAll (since July 2017)
if strings.EqualFold(provider.GetString("serviceDomainMatchAll"), "true") {
sr.ServiceDomainAlgo = "hdr_dom(host)"
Expand All @@ -272,26 +274,26 @@ func GetServiceFromProvider(provider ServiceParameterProvider) *Service {
sr.HttpsPort, _ = strconv.Atoi(provider.GetString("httpsPort"))
}
if len(provider.GetString("addReqHeader")) > 0 {
sr.AddReqHeader = strings.Split(provider.GetString("addReqHeader"), ",")
sr.AddReqHeader = strings.Split(provider.GetString("addReqHeader"), separator)
} else if len(provider.GetString("addHeader")) > 0 { // TODO: Deprecated since Apr. 2017.
sr.AddReqHeader = strings.Split(provider.GetString("addHeader"), ",")
sr.AddReqHeader = strings.Split(provider.GetString("addHeader"), separator)
}
if len(provider.GetString("setReqHeader")) > 0 {
sr.SetReqHeader = strings.Split(provider.GetString("setReqHeader"), ",")
sr.SetReqHeader = strings.Split(provider.GetString("setReqHeader"), separator)
} else if len(provider.GetString("setHeader")) > 0 { // TODO: Deprecated since Apr. 2017.
sr.SetReqHeader = strings.Split(provider.GetString("setHeader"), ",")
sr.SetReqHeader = strings.Split(provider.GetString("setHeader"), separator)
}
if len(provider.GetString("delReqHeader")) > 0 {
sr.DelReqHeader = strings.Split(provider.GetString("delReqHeader"), ",")
sr.DelReqHeader = strings.Split(provider.GetString("delReqHeader"), separator)
}
if len(provider.GetString("addResHeader")) > 0 {
sr.AddResHeader = strings.Split(provider.GetString("addResHeader"), ",")
sr.AddResHeader = strings.Split(provider.GetString("addResHeader"), separator)
}
if len(provider.GetString("setResHeader")) > 0 {
sr.SetResHeader = strings.Split(provider.GetString("setResHeader"), ",")
sr.SetResHeader = strings.Split(provider.GetString("setResHeader"), separator)
}
if len(provider.GetString("delResHeader")) > 0 {
sr.DelResHeader = strings.Split(provider.GetString("delResHeader"), ",")
sr.DelResHeader = strings.Split(provider.GetString("delResHeader"), separator)
}
if len(sr.SessionType) > 0 {
sr.Tasks, _ = lookupHost("tasks." + sr.ServiceName)
Expand Down Expand Up @@ -350,13 +352,14 @@ func getServiceDestList(sr *Service, provider ServiceParameterProvider) []Servic
}

func getServiceDest(sr *Service, provider ServiceParameterProvider, index int) ServiceDest {
separator := os.Getenv("SEPARATOR")
suffix := ""
if index > 0 {
suffix = fmt.Sprintf(".%d", index)
}
userAgent := UserAgent{}
if len(provider.GetString(fmt.Sprintf("userAgent%s", suffix))) > 0 {
userAgent.Value = strings.Split(provider.GetString(fmt.Sprintf("userAgent%s", suffix)), ",")
userAgent.Value = strings.Split(provider.GetString(fmt.Sprintf("userAgent%s", suffix)), separator)
userAgent.AclName = replaceNonAlphabetAndNumbers(userAgent.Value)
}
reqMode := "http"
Expand All @@ -367,7 +370,7 @@ func getServiceDest(sr *Service, provider ServiceParameterProvider, index int) S
headerString := provider.GetString(fmt.Sprintf("serviceHeader%s", suffix))
header := map[string]string{}
if len(headerString) > 0 {
for _, value := range strings.Split(headerString, ",") {
for _, value := range strings.Split(headerString, separator) {
values := strings.Split(value, ":")
if len(values) == 2 {
header[strings.Trim(values[0], " ")] = strings.Trim(values[1], " ")
Expand Down Expand Up @@ -397,9 +400,10 @@ func getServiceDest(sr *Service, provider ServiceParameterProvider, index int) S
}

func getSliceFromString(provider ServiceParameterProvider, key string) []string {
separator := os.Getenv("SEPARATOR")
value := []string{}
if len(provider.GetString(key)) > 0 {
value = strings.Split(provider.GetString(key), ",")
value = strings.Split(provider.GetString(key), separator)
}
return value
}
Expand Down
Loading

0 comments on commit 1ad9856

Please sign in to comment.