github.com/thanos-io/thanos@v0.32.5/internal/cortex/tenant/resolver.go (about) 1 // Copyright (c) The Cortex Authors. 2 // Licensed under the Apache License 2.0. 3 4 package tenant 5 6 import ( 7 "context" 8 "errors" 9 "strings" 10 11 "github.com/weaveworks/common/user" 12 ) 13 14 var defaultResolver Resolver = NewSingleResolver() 15 16 // TenantID returns exactly a single tenant ID from the context. It should be 17 // used when a certain endpoint should only support exactly a single 18 // tenant ID. It returns an error user.ErrNoOrgID if there is no tenant ID 19 // supplied or user.ErrTooManyOrgIDs if there are multiple tenant IDs present. 20 // 21 // ignore stutter warning 22 // 23 //nolint:golint 24 func TenantID(ctx context.Context) (string, error) { 25 return defaultResolver.TenantID(ctx) 26 } 27 28 // TenantIDs returns all tenant IDs from the context. It should return 29 // normalized list of ordered and distinct tenant IDs (as produced by 30 // NormalizeTenantIDs). 31 // 32 // ignore stutter warning 33 // 34 //nolint:golint 35 func TenantIDs(ctx context.Context) ([]string, error) { 36 return defaultResolver.TenantIDs(ctx) 37 } 38 39 type Resolver interface { 40 // TenantID returns exactly a single tenant ID from the context. It should be 41 // used when a certain endpoint should only support exactly a single 42 // tenant ID. It returns an error user.ErrNoOrgID if there is no tenant ID 43 // supplied or user.ErrTooManyOrgIDs if there are multiple tenant IDs present. 44 TenantID(context.Context) (string, error) 45 46 // TenantIDs returns all tenant IDs from the context. It should return 47 // normalized list of ordered and distinct tenant IDs (as produced by 48 // NormalizeTenantIDs). 49 TenantIDs(context.Context) ([]string, error) 50 } 51 52 // NewSingleResolver creates a tenant resolver, which restricts all requests to 53 // be using a single tenant only. This allows a wider set of characters to be 54 // used within the tenant ID and should not impose a breaking change. 55 func NewSingleResolver() *SingleResolver { 56 return &SingleResolver{} 57 } 58 59 type SingleResolver struct { 60 } 61 62 // containsUnsafePathSegments will return true if the string is a directory 63 // reference like `.` and `..` or if any path separator character like `/` and 64 // `\` can be found. 65 func containsUnsafePathSegments(id string) bool { 66 // handle the relative reference to current and parent path. 67 if id == "." || id == ".." { 68 return true 69 } 70 71 return strings.ContainsAny(id, "\\/") 72 } 73 74 var errInvalidTenantID = errors.New("invalid tenant ID") 75 76 func (t *SingleResolver) TenantID(ctx context.Context) (string, error) { 77 //lint:ignore faillint wrapper around upstream method 78 id, err := user.ExtractOrgID(ctx) 79 if err != nil { 80 return "", err 81 } 82 83 if containsUnsafePathSegments(id) { 84 return "", errInvalidTenantID 85 } 86 87 return id, nil 88 } 89 90 func (t *SingleResolver) TenantIDs(ctx context.Context) ([]string, error) { 91 orgID, err := t.TenantID(ctx) 92 if err != nil { 93 return nil, err 94 } 95 return []string{orgID}, err 96 }