Skip to content

Commit 5df4598

Browse files
authored
Validate tenantID on single resolver (#6727)
Signed-off-by: SungJin1212 <[email protected]>
1 parent 0b8c593 commit 5df4598

File tree

5 files changed

+55
-45
lines changed

5 files changed

+55
-45
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## master / unreleased
44
* [CHANGE] Ingester: Remove EnableNativeHistograms config flag and instead gate keep through new per-tenant limit at ingestion. #6718
55
* [CHANGE] StoreGateway/Alertmanager: Add default 5s connection timeout on client. #6603
6+
* [CHANGE] Validate a tenantID when to use a single tenant resolver. #6727
67
* [FEATURE] Query Frontend: Add dynamic interval size for query splitting. This is enabled by configuring experimental flags `querier.max-shards-per-query` and/or `querier.max-fetched-data-duration-per-query`. The split interval size is dynamically increased to maintain a number of shards and total duration fetched below the configured values. #6458
78
* [FEATURE] Querier/Ruler: Add `query_partial_data` and `rules_partial_data` limits to allow queries/rules to be evaluated with data from a single zone, if other zones are not available. #6526
89
* [FEATURE] Update prometheus alertmanager version to v0.28.0 and add new integration msteamsv2, jira, and rocketchat. #6590

pkg/tenant/resolver.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package tenant
22

33
import (
44
"context"
5-
"errors"
65
"net/http"
76
"strings"
87

@@ -67,24 +66,18 @@ type SingleResolver struct {
6766
// `\` can be found.
6867
func containsUnsafePathSegments(id string) bool {
6968
// handle the relative reference to current and parent path.
70-
if id == "." || id == ".." {
71-
return true
72-
}
73-
74-
return strings.ContainsAny(id, "\\/")
69+
return id == "." || id == ".."
7570
}
7671

77-
var errInvalidTenantID = errors.New("invalid tenant ID")
78-
7972
func (t *SingleResolver) TenantID(ctx context.Context) (string, error) {
8073
//lint:ignore faillint wrapper around upstream method
8174
id, err := user.ExtractOrgID(ctx)
8275
if err != nil {
8376
return "", err
8477
}
8578

86-
if containsUnsafePathSegments(id) {
87-
return "", errInvalidTenantID
79+
if err := ValidTenantID(id); err != nil {
80+
return "", err
8881
}
8982

9083
return id, nil
@@ -134,9 +127,6 @@ func (t *MultiResolver) TenantIDs(ctx context.Context) ([]string, error) {
134127
if err := ValidTenantID(orgID); err != nil {
135128
return nil, err
136129
}
137-
if containsUnsafePathSegments(orgID) {
138-
return nil, errInvalidTenantID
139-
}
140130
}
141131

142132
return NormalizeTenantIDs(orgIDs), nil

pkg/tenant/resolver_test.go

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -67,37 +67,49 @@ var commonResolverTestCases = []resolverTestCase{
6767
{
6868
name: "parent-dir",
6969
headerValue: strptr(".."),
70-
errTenantID: errInvalidTenantID,
71-
errTenantIDs: errInvalidTenantID,
70+
errTenantID: errTenantIDUnsafe,
71+
errTenantIDs: errTenantIDUnsafe,
7272
},
7373
{
7474
name: "current-dir",
7575
headerValue: strptr("."),
76-
errTenantID: errInvalidTenantID,
77-
errTenantIDs: errInvalidTenantID,
76+
errTenantID: errTenantIDUnsafe,
77+
errTenantIDs: errTenantIDUnsafe,
78+
},
79+
{
80+
name: "white space",
81+
headerValue: strptr(" "),
82+
errTenantID: &errTenantIDUnsupportedCharacter{pos: 0, tenantID: " "},
83+
errTenantIDs: &errTenantIDUnsupportedCharacter{pos: 0, tenantID: " "},
84+
},
85+
{
86+
name: "containing-forward-slash",
87+
headerValue: strptr("forward/slash"),
88+
errTenantID: &errTenantIDUnsupportedCharacter{pos: 7, tenantID: "forward/slash"},
89+
errTenantIDs: &errTenantIDUnsupportedCharacter{pos: 7, tenantID: "forward/slash"},
90+
},
91+
{
92+
name: "containing-backward-slash",
93+
headerValue: strptr(`backward\slash`),
94+
errTenantID: &errTenantIDUnsupportedCharacter{pos: 8, tenantID: "backward\\slash"},
95+
errTenantIDs: &errTenantIDUnsupportedCharacter{pos: 8, tenantID: "backward\\slash"},
7896
},
7997
}
8098

8199
func TestSingleResolver(t *testing.T) {
82100
r := NewSingleResolver()
83101
for _, tc := range append(commonResolverTestCases, []resolverTestCase{
84102
{
85-
name: "multi-tenant",
86-
headerValue: strptr("tenant-a|tenant-b"),
87-
tenantID: "tenant-a|tenant-b",
88-
tenantIDs: []string{"tenant-a|tenant-b"},
89-
},
90-
{
91-
name: "containing-forward-slash",
92-
headerValue: strptr("forward/slash"),
93-
errTenantID: errInvalidTenantID,
94-
errTenantIDs: errInvalidTenantID,
103+
name: "multi-tenant",
104+
headerValue: strptr("tenant-a|tenant-b"),
105+
errTenantID: &errTenantIDUnsupportedCharacter{pos: 8, tenantID: "tenant-a|tenant-b"},
106+
errTenantIDs: &errTenantIDUnsupportedCharacter{pos: 8, tenantID: "tenant-a|tenant-b"},
95107
},
96108
{
97-
name: "containing-backward-slash",
98-
headerValue: strptr(`backward\slash`),
99-
errTenantID: errInvalidTenantID,
100-
errTenantIDs: errInvalidTenantID,
109+
name: "containing-invalid-character",
110+
headerValue: strptr("+"),
111+
errTenantID: &errTenantIDUnsupportedCharacter{pos: 0, tenantID: "+"},
112+
errTenantIDs: &errTenantIDUnsupportedCharacter{pos: 0, tenantID: "+"},
101113
},
102114
}...) {
103115
t.Run(tc.name, tc.test(r))
@@ -126,22 +138,16 @@ func TestMultiResolver(t *testing.T) {
126138
tenantIDs: []string{"tenant-a", "tenant-b"},
127139
},
128140
{
129-
name: "multi-tenant-with-relative-path",
130-
headerValue: strptr("tenant-a|tenant-b|.."),
131-
errTenantID: errInvalidTenantID,
132-
errTenantIDs: errInvalidTenantID,
141+
name: "multi-tenant-with-unsafe-path-segment(.)",
142+
headerValue: strptr("tenant-a|tenant-b|."),
143+
errTenantID: errTenantIDUnsafe,
144+
errTenantIDs: errTenantIDUnsafe,
133145
},
134146
{
135-
name: "containing-forward-slash",
136-
headerValue: strptr("forward/slash"),
137-
errTenantID: &errTenantIDUnsupportedCharacter{pos: 7, tenantID: "forward/slash"},
138-
errTenantIDs: &errTenantIDUnsupportedCharacter{pos: 7, tenantID: "forward/slash"},
139-
},
140-
{
141-
name: "containing-backward-slash",
142-
headerValue: strptr(`backward\slash`),
143-
errTenantID: &errTenantIDUnsupportedCharacter{pos: 8, tenantID: "backward\\slash"},
144-
errTenantIDs: &errTenantIDUnsupportedCharacter{pos: 8, tenantID: "backward\\slash"},
147+
name: "multi-tenant-with-unsafe-path-segment(..)",
148+
headerValue: strptr("tenant-a|tenant-b|.."),
149+
errTenantID: errTenantIDUnsafe,
150+
errTenantIDs: errTenantIDUnsafe,
145151
},
146152
}...) {
147153
t.Run(tc.name, tc.test(r))

pkg/tenant/tenant.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
var (
1414
errTenantIDTooLong = errors.New("tenant ID is too long: max 150 characters")
15+
errTenantIDUnsafe = errors.New("tenant ID is '.' or '..'")
1516
)
1617

1718
type errTenantIDUnsupportedCharacter struct {
@@ -65,6 +66,10 @@ func ValidTenantID(s string) error {
6566
return errTenantIDTooLong
6667
}
6768

69+
if containsUnsafePathSegments(s) {
70+
return errTenantIDUnsafe
71+
}
72+
6873
return nil
6974
}
7075

pkg/tenant/tenant_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ func TestValidTenantIDs(t *testing.T) {
2929
name: strings.Repeat("a", 151),
3030
err: strptr("tenant ID is too long: max 150 characters"),
3131
},
32+
{
33+
name: ".",
34+
err: strptr("tenant ID is '.' or '..'"),
35+
},
36+
{
37+
name: "..",
38+
err: strptr("tenant ID is '.' or '..'"),
39+
},
3240
} {
3341
t.Run(tc.name, func(t *testing.T) {
3442
err := ValidTenantID(tc.name)

0 commit comments

Comments
 (0)