Team LBAC: Limit access to data source (#78376)

* Team LBAC: Limit access to data source

* Fix tests
This commit is contained in:
Alexander Zobnin
2023-12-05 12:45:40 +01:00
committed by GitHub
parent d099292d99
commit 043096d652
4 changed files with 76 additions and 56 deletions

View File

@@ -376,9 +376,12 @@ func validateTeamHTTPHeaderJSON(jsonData *simplejson.Json) error {
datasourcesLogger.Error("Unable to marshal TeamHTTPHeaders") datasourcesLogger.Error("Unable to marshal TeamHTTPHeaders")
return errors.New("validation error, invalid format of TeamHTTPHeaders") return errors.New("validation error, invalid format of TeamHTTPHeaders")
} }
if teamHTTPHeadersJSON == nil {
return nil
}
// whitelisting ValidHeaders // whitelisting ValidHeaders
// each teams headers // each teams headers
for _, teamheaders := range teamHTTPHeadersJSON { for _, teamheaders := range teamHTTPHeadersJSON.Headers {
for _, header := range teamheaders { for _, header := range teamheaders {
if !slices.ContainsFunc(validHeaders, func(v string) bool { if !slices.ContainsFunc(validHeaders, func(v string) bool {
return http.CanonicalHeaderKey(v) == http.CanonicalHeaderKey(header.Header) return http.CanonicalHeaderKey(v) == http.CanonicalHeaderKey(header.Header)

View File

@@ -233,47 +233,52 @@ func TestUpdateDataSourceTeamHTTPHeaders_InvalidJSONData(t *testing.T) {
}{ }{
{ {
desc: "We should only allow for headers being X-Prom-Label-Policy", desc: "We should only allow for headers being X-Prom-Label-Policy",
data: datasources.TeamHTTPHeaders{tenantID: []datasources.TeamHTTPHeader{ data: datasources.TeamHTTPHeaders{
Headers: datasources.TeamHeaders{
tenantID: []datasources.TeamHTTPHeader{
{ {
Header: "Authorization", Header: "Authorization",
Value: "foo!=bar", Value: "foo!=bar",
}, },
}, },
}, }},
want: 400, want: 400,
}, },
{ {
desc: "Allowed header but no team id", desc: "Allowed header but no team id",
data: datasources.TeamHTTPHeaders{"": []datasources.TeamHTTPHeader{ data: datasources.TeamHTTPHeaders{
Headers: datasources.TeamHeaders{"": []datasources.TeamHTTPHeader{
{ {
Header: "X-Prom-Label-Policy", Header: "X-Prom-Label-Policy",
Value: "foo=bar", Value: "foo=bar",
}, },
}, },
}, }},
want: 400, want: 400,
}, },
{ {
desc: "Allowed team id and header name with invalid header values ", desc: "Allowed team id and header name with invalid header values ",
data: datasources.TeamHTTPHeaders{tenantID: []datasources.TeamHTTPHeader{ data: datasources.TeamHTTPHeaders{
Headers: datasources.TeamHeaders{tenantID: []datasources.TeamHTTPHeader{
{ {
Header: "X-Prom-Label-Policy", Header: "X-Prom-Label-Policy",
Value: "Bad value", Value: "Bad value",
}, },
}, },
}, }},
want: 400, want: 400,
}, },
// Complete valid case, with team id, header name and header value // Complete valid case, with team id, header name and header value
{ {
desc: "Allowed header and header values ", desc: "Allowed header and header values ",
data: datasources.TeamHTTPHeaders{tenantID: []datasources.TeamHTTPHeader{ data: datasources.TeamHTTPHeaders{
Headers: datasources.TeamHeaders{tenantID: []datasources.TeamHTTPHeader{
{ {
Header: "X-Prom-Label-Policy", Header: "X-Prom-Label-Policy",
Value: `1234:{ name!="value",foo!~"bar" }`, Value: `1234:{ name!="value",foo!~"bar" }`,
}, },
}, },
}, }},
want: 200, want: 200,
}, },
} }

View File

@@ -71,7 +71,12 @@ type TeamHTTPHeadersJSONData struct {
TeamHTTPHeaders TeamHTTPHeaders `json:"teamHttpHeaders"` TeamHTTPHeaders TeamHTTPHeaders `json:"teamHttpHeaders"`
} }
type TeamHTTPHeaders map[string][]TeamHTTPHeader type TeamHTTPHeaders struct {
Headers TeamHeaders `json:"headers"`
RestrictAccess bool `json:"restrictAccess"`
}
type TeamHeaders map[string][]TeamHTTPHeader
type TeamHTTPHeader struct { type TeamHTTPHeader struct {
Header string `json:"header"` Header string `json:"header"`
@@ -80,22 +85,28 @@ type TeamHTTPHeader struct {
const DefaultTeamHTTPHeader = "default" const DefaultTeamHTTPHeader = "default"
func (ds DataSource) TeamHTTPHeaders() (TeamHTTPHeaders, error) { func (ds DataSource) TeamHTTPHeaders() (*TeamHTTPHeaders, error) {
return GetTeamHTTPHeaders(ds.JsonData) return GetTeamHTTPHeaders(ds.JsonData)
} }
func GetTeamHTTPHeaders(jsonData *simplejson.Json) (TeamHTTPHeaders, error) { func GetTeamHTTPHeaders(jsonData *simplejson.Json) (*TeamHTTPHeaders, error) {
teamHTTPHeadersJSON := TeamHTTPHeaders{} teamHTTPHeaders := &TeamHTTPHeaders{}
if jsonData != nil && jsonData.Get("teamHttpHeaders") != nil { if jsonData == nil {
jsonData, err := jsonData.Get("teamHttpHeaders").MarshalJSON() return nil, nil
}
if _, ok := jsonData.CheckGet("teamHttpHeaders"); !ok {
return nil, nil
}
teamHTTPHeadersJSON, err := jsonData.Get("teamHttpHeaders").MarshalJSON()
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = json.Unmarshal(jsonData, &teamHTTPHeadersJSON) err = json.Unmarshal(teamHTTPHeadersJSON, teamHTTPHeaders)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for teamID, headers := range teamHTTPHeadersJSON { for teamID, headers := range teamHTTPHeaders.Headers {
if teamID == "" { if teamID == "" {
return nil, errors.New("teamID is missing or empty in teamHttpHeaders") return nil, errors.New("teamID is missing or empty in teamHttpHeaders")
} }
@@ -109,9 +120,8 @@ func GetTeamHTTPHeaders(jsonData *simplejson.Json) (TeamHTTPHeaders, error) {
} }
} }
} }
}
return teamHTTPHeadersJSON, nil return teamHTTPHeaders, nil
} }
// AllowedCookies parses the jsondata.keepCookies and returns a list of // AllowedCookies parses the jsondata.keepCookies and returns a list of

View File

@@ -63,17 +63,19 @@ func TestTeamHTTPHeaders(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
given string given string
want TeamHTTPHeaders want *TeamHTTPHeaders
}{ }{
{ {
desc: "Usual json data with teamHttpHeaders", desc: "Usual json data with teamHttpHeaders",
given: `{"teamHttpHeaders": {"101": [{"header": "X-CUSTOM-HEADER", "value": "foo"}]}}`, given: `{"teamHttpHeaders": {"headers": {"101": [{"header": "X-CUSTOM-HEADER", "value": "foo"}]}}}`,
want: TeamHTTPHeaders{ want: &TeamHTTPHeaders{
Headers: TeamHeaders{
"101": { "101": {
{Header: "X-CUSTOM-HEADER", Value: "foo"}, {Header: "X-CUSTOM-HEADER", Value: "foo"},
}, },
}, },
}, },
},
{ {
desc: "Json data without teamHttpHeaders", desc: "Json data without teamHttpHeaders",
given: `{"foo": "bar"}`, given: `{"foo": "bar"}`,