in xds/httpfilter/rbac/rbac.go [89:155]
func parseConfig(rbacCfg *rpb.RBAC) (httpfilter.FilterConfig, error) {
// All the validation logic described in A41.
for _, policy := range rbacCfg.GetRules().GetPolicies() {
// "Policy.condition and Policy.checked_condition must cause a
// validation failure if present." - A41
if policy.Condition != nil {
return nil, errors.New("rbac: Policy.condition is present")
}
if policy.CheckedCondition != nil {
return nil, errors.New("rbac: policy.CheckedCondition is present")
}
// "It is also a validation failure if Permission or Principal has a
// header matcher for a grpc- prefixed header name or :scheme." - A41
for _, principal := range policy.Principals {
name := principal.GetHeader().GetName()
if name == ":scheme" || strings.HasPrefix(name, "grpc-") {
return nil, fmt.Errorf("rbac: principal header matcher for %v is :scheme or starts with grpc", name)
}
}
for _, permission := range policy.Permissions {
name := permission.GetHeader().GetName()
if name == ":scheme" || strings.HasPrefix(name, "grpc-") {
return nil, fmt.Errorf("rbac: permission header matcher for %v is :scheme or starts with grpc", name)
}
}
}
// "Envoy aliases :authority and Host in its header map implementation, so
// they should be treated equivalent for the RBAC matchers; there must be no
// behavior change depending on which of the two header names is used in the
// RBAC policy." - A41. Loop through config's principals and policies, change
// any header matcher with value "host" to :authority", as that is what
// grpc-go shifts both headers to in transport layer.
for _, policy := range rbacCfg.GetRules().GetPolicies() {
for _, principal := range policy.Principals {
if principal.GetHeader().GetName() == "host" {
principal.GetHeader().Name = ":authority"
}
}
for _, permission := range policy.Permissions {
if permission.GetHeader().GetName() == "host" {
permission.GetHeader().Name = ":authority"
}
}
}
// Two cases where this HTTP Filter is a no op:
// "If absent, no enforcing RBAC policy will be applied" - RBAC
// Documentation for Rules field.
// "At this time, if the RBAC.action is Action.LOG then the policy will be
// completely ignored, as if RBAC was not configurated." - A41
if rbacCfg.Rules == nil || rbacCfg.GetRules().GetAction() == v3rbacpb.RBAC_LOG {
return config{}, nil
}
ce, err := rbac.NewChainEngine([]*v3rbacpb.RBAC{rbacCfg.GetRules()})
if err != nil {
// "At this time, if the RBAC.action is Action.LOG then the policy will be
// completely ignored, as if RBAC was not configurated." - A41
if rbacCfg.GetRules().GetAction() != v3rbacpb.RBAC_LOG {
return nil, fmt.Errorf("rbac: error constructing matching engine: %v", err)
}
}
return config{chainEngine: ce}, nil
}