Skip to content

Commit 3370eb2

Browse files
oliwermjuraga
authored andcommitted
BUG/MINOR: detect when a raw configuration is uploaded incorrectly
Return an error when the user tries to upload an HAProxy configuration file without any newline character. This can happen for example when using curl(1) with bad options: # BAD! This will url-encode the file. curl -H 'Content-Type: text/plain' -d @haproxy.cfg $URL # GOOD. Upload without encoding. curl -H 'Content-Type: text/plain' -T haproxy.cfg $URL Note that we still allow to upload an empty configuration, since this is supported by HAProxy in master-worker mode, and it may actually be useful in future releases.
1 parent beb7e30 commit 3370eb2

File tree

6 files changed

+139
-0
lines changed

6 files changed

+139
-0
lines changed

e2e/tests/raw/data/haproxy.cfg

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
global
2+
chroot /var/lib/haproxy
3+
user haproxy
4+
group haproxy
5+
maxconn 4000
6+
pidfile /var/run/haproxy.pid
7+
stats socket /var/lib/haproxy/stats level admin
8+
log 127.0.0.1 local2
9+
10+
defaults
11+
mode http
12+
maxconn 3000
13+
log global
14+
option httplog
15+
option redispatch
16+
option dontlognull
17+
option http-server-close
18+
option forwardfor except 127.0.0.0/8
19+
timeout http-request 10s
20+
timeout check 10s
21+
timeout connect 10s
22+
timeout client 1m
23+
timeout queue 1m
24+
timeout server 1m
25+
timeout http-keep-alive 10s
26+
retries 3
27+
28+
backend test_backend
29+
mode http
30+
balance roundrobin
31+
option forwardfor
32+
server server_01 10.1.1.1:8080 check weight 80
33+
server server_02 10.1.1.2:8080 check weight 80
34+
server server_03 10.1.1.2:8080 check weight 80

e2e/tests/raw/data/haproxy.cfg.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"global\n chroot /var/lib/haproxy\n user haproxy\n group haproxy\n maxconn 4000\n pidfile /var/run/haproxy.pid\n stats socket /var/lib/haproxy/stats level admin\n log 127.0.0.1 local2\n\ndefaults\n mode http\n maxconn 3000\n log global\n option httplog\n option redispatch\n option dontlognull\n option http-server-close\n option forwardfor except 127.0.0.0/8\n timeout http-request 10s\n timeout check 10s\n timeout connect 10s\n timeout client 1m\n timeout queue 1m\n timeout server 1m\n timeout http-keep-alive 10s\n retries 3\n\nbackend test_backend\n mode http\n balance roundrobin\n option forwardfor\n server server_01 10.1.1.1:8080 check weight 80\n server server_02 10.1.1.2:8080 check weight 80\n server server_03 10.1.1.2:8080 check weight 80\n"

e2e/tests/raw/get.bats

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env bats
2+
#
3+
# Copyright 2023 HAProxy Technologies
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http:#www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
load '../../libs/dataplaneapi'
19+
load "../../libs/get_json_path"
20+
load '../../libs/haproxy_config_setup'
21+
load '../../libs/resource_client'
22+
23+
load 'utils/_helpers'
24+
25+
@test "raw: Download configuration" {
26+
resource_get "$_RAW_BASE_PATH"
27+
assert_equal "$SC" 200
28+
test -n "$(get_json_path "$BODY" .data)" ||
29+
fail "failed to download raw config. BODY: '$BODY'"
30+
}

e2e/tests/raw/post.bats

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env bats
2+
#
3+
# Copyright 2023 HAProxy Technologies
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http:#www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
load '../../libs/dataplaneapi'
19+
load '../../libs/debug'
20+
load "../../libs/get_json_path"
21+
load '../../libs/haproxy_config_setup'
22+
load '../../libs/resource_client'
23+
load '../../libs/version'
24+
25+
load 'utils/_helpers'
26+
27+
@test "raw: Post new configuration" {
28+
resource_post "$_RAW_BASE_PATH" 'data/haproxy.cfg.json'
29+
assert_equal "$SC" 202
30+
}
31+
32+
@test "raw: Post new configuration incorrectly (bug 1219)" {
33+
resource_post_text "$_RAW_BASE_PATH" 'data/haproxy.cfg.json'
34+
assert_equal "$SC" 400
35+
assert_equal "$(get_json_path "$BODY" '.message')" "invalid configuration: no newline character found"
36+
}

e2e/tests/raw/utils/_helpers.bash

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Copyright 2023 HAProxy Technologies
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http:#www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
_RAW_BASE_PATH="/services/haproxy/configuration/raw"
19+
20+
# Identical to resource_post() but with the text/plain content type.
21+
function resource_post_text() {
22+
local endpoint="$1" data="@${BATS_TEST_DIRNAME}/$2" qs_params="$3"
23+
24+
run curl -m 10 -s -H 'content-type: text/plain' --user dataplaneapi:mypassword \
25+
"-XPOST" -w "\n%{http_code}" "-d${data}" \
26+
"http://${LOCAL_IP_ADDRESS}:${E2E_PORT}${BASE_PATH}${endpoint}?$qs_params&version=$(version)"
27+
assert_success
28+
dpa_curl_status_body '$output'
29+
}

handlers/raw.go

+9
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@ func (h *PostRawConfigurationHandlerImpl) Handle(params configuration.PostHAProx
9595
onlyValidate = *params.OnlyValidate
9696
}
9797

98+
// Check for a common error where the user ran `curl -d @haproxy.cfg` without
99+
// converting the file to json, which removes all the \n from the configuration.
100+
if len(params.Data) > 0 && !strings.ContainsRune(params.Data, '\n') {
101+
code := misc.ErrHTTPBadRequest
102+
msg := "invalid configuration: no newline character found"
103+
e := &models.Error{Code: &code, Message: &msg}
104+
return configuration.NewPostHAProxyConfigurationBadRequest().WithPayload(e)
105+
}
106+
98107
cfg, err := h.Client.Configuration()
99108
if err != nil {
100109
e := misc.HandleError(err)

0 commit comments

Comments
 (0)