hashicorp / hashicorp/consul

403 Forbidden / 404 Not Found from KV GET requests depending on 'recurse' parameter

Open
#10,222 0 comments 0 reactions 0 assignees View on GitHub
theme/api type/enhancement type/question
Dominant language
Go
Stars
30.1k
Forks
4.6k
Avg merge
1d 18h
Merged PRs (30d)
39

Description

#### Overview of the Issue

My setup consists of 1 server, 2 agents and ACLs enabled.
When I attempt to submit a GET requests on KV using a token with no permissions on the KV store and the `recurse` parameter set, I get a **404 Not Found** error while I'd expect to receive a **403 Forbidden**.

#### Reproduction Steps
1. Create some nested entries in the KV store
```
consul kv put foo/a aaa
consul kv put foo/b bbb
consul kv put foo/c ccc
```

2. Attempt to retrieve a specific key via HTTP API using a token without permissions (CORRECT)
```
$ curl -sv "http://127.0.0.1:8500/v1/kv/foo?token=anonymous"
* About to connect() to 127.0.0.1 port 8500 (#0)
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8500 (#0)
> GET /v1/kv/foo?token=anonymous HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:8500
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Vary: Accept-Encoding
< X-Consul-Default-Acl-Policy: deny
< Date: Tue, 11 May 2021 11:27:26 GMT
< Content-Length: 40
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host 127.0.0.1 left intact
rpc error making call: Permission denied
```

3. Attempt to retrieve a key via HTTP API using a token without permissions and `recurse` parameter set (**WRONG**)
```
$ curl -sv "http://127.0.0.1:8500/v1/kv/foo/?token=anonymous&recurse="
* About to connect() to 127.0.0.1 port 8500 (#0)
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8500 (#0)
> GET /v1/kv/foo/?token=anonymous&recurse= HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:8500
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Vary: Accept-Encoding
< X-Consul-Default-Acl-Policy: deny
< X-Consul-Index: 34405
< X-Consul-Knownleader: true
< X-Consul-Lastcontact: 0
< Date: Tue, 11 May 2021 11:33:26 GMT
< Content-Length: 0
<
* Connection #0 to host 127.0.0.1 left intact
```

4. Same request as above but with valid token this time (CORRECT)
```
$ curl -sv "http://127.0.0.1:8500/v1/kv/foo/?token=&recurse="
* About to connect() to 127.0.0.1 port 8500 (#0)
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8500 (#0)
> GET /v1/kv/foo/?token=&recurse= HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:8500
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Vary: Accept-Encoding
< X-Consul-Default-Acl-Policy: deny
< X-Consul-Index: 34405
< X-Consul-Knownleader: true
< X-Consul-Lastcontact: 0
< Date: Tue, 11 May 2021 11:33:44 GMT
< Content-Length: 286
<
* Connection #0 to host 127.0.0.1 left intact
[{"LockIndex":0,"Key":"foo/a","Flags":0,"Value":"YWFh","CreateIndex":34402,"ModifyIndex":34402},{"LockIndex":0,"Key":"foo/b","Flags":0,"Value":"YmJi","CreateIndex":34404,"ModifyIndex":34404},{"LockIndex":0,"Key":"foo/c","Flags":0,"Value":"Y2Nj","CreateIndex":34405,"ModifyIndex":34405}]
```

The behavior is the same whether the request is made to the client or to the server.

### Consul info for both Client and Server

Client info

```
agent:
check_monitors = 0
check_ttls = 0
checks = 0
services = 0
build:
prerelease =
revision = 3c1c2267
version = 1.9.5
consul:
acl = enabled
known_servers = 1
server = false
runtime:
arch = amd64
cpu_count = 2
goroutines = 54
max_procs = 2
os = linux
version = go1.15.8
serf_lan:
coordinate_resets = 0
encrypted = true
event_queue = 0
event_time = 2
failed = 0
health_score = 0
intent_queue = 0
left = 0
member_time = 105
members = 2
query_queue = 0
query_time = 1
```

Server info

```
agent:
check_monitors = 0
check_ttls = 0
checks = 0
services = 0
build:
prerelease =
revision = 3c1c2267
version = 1.9.5
consul:
acl = enabled
bootstrap = true
known_datacenters = 1
leader = true
leader_addr = 10.42.0.16:8300
server = true
raft:
applied_index = 34583
commit_index = 34583
fsm_pending = 0
last_contact = 0
last_log_index = 34583
last_log_term = 7
last_snapshot_index = 19873
last_snapshot_term = 6
latest_configuration = [{Suffrage:Voter ID:6997cba7-08bd-cdac-eb46-fe51befbe3a5 Address:10.42.0.16:8300}]
latest_configuration_index = 0
num_peers = 0
protocol_version = 3
protocol_version_max = 3
protocol_version_min = 0
snapshot_version_max = 1
snapshot_version_min = 0
state = Leader
term = 7
runtime:
arch = amd64
cpu_count = 2
goroutines = 102
max_procs = 2
os = linux
version = go1.15.8
serf_lan:
coordinate_resets = 0
encrypted = true
event_queue = 0
event_time = 2
failed = 0
health_score = 0
intent_queue = 0
left = 0
member_time = 105
members = 2
query_queue = 0
query_time = 1
serf_wan:
coordinate_resets = 0
encrypted = true
event_queue = 0
event_time = 1
failed = 0
health_score = 0
intent_queue = 0
left = 0
member_time = 4
members = 1
query_queue = 0
query_time = 1
```

### Operating system and Environment details

Red Hat Linux Enterprise 7, x86_64

Contributor guide

Open the contributing guide

Research direction

Reproduce the issue against the /v1/kv endpoint using an ACL-denied token, comparing requests with and without recurse. Trace the Go HTTP handling and authorization response path; done means the denied recursive request returns 403 Forbidden, while the valid-token request continues to return 200 OK.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, authorization
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.