mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-05-07 06:02:09 +08:00
734 lines
18 KiB
Go
734 lines
18 KiB
Go
// Copyright 2019 Yunion
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package rbacutils
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/log"
|
|
"yunion.io/x/pkg/errors"
|
|
"yunion.io/x/pkg/util/netutils"
|
|
)
|
|
|
|
type TRbacResult string
|
|
type TRbacScope string
|
|
|
|
const (
|
|
WILD_MATCH = "*"
|
|
|
|
Allow = TRbacResult("allow")
|
|
Deny = TRbacResult("deny")
|
|
|
|
// no more many allow levels, only allow/deny
|
|
|
|
AdminAllow = TRbacResult("admin") // deprecated
|
|
OwnerAllow = TRbacResult("owner") // deprecated
|
|
UserAllow = TRbacResult("user") // deprecated
|
|
GuestAllow = TRbacResult("guest") // deprecated
|
|
|
|
ScopeSystem = TRbacScope("system")
|
|
ScopeDomain = TRbacScope("domain")
|
|
ScopeProject = TRbacScope("project")
|
|
// ScopeObject = "object"
|
|
ScopeUser = TRbacScope("user")
|
|
ScopeNone = TRbacScope("none")
|
|
)
|
|
|
|
var (
|
|
strictness = map[TRbacResult]int{
|
|
Deny: 0,
|
|
AdminAllow: 1,
|
|
OwnerAllow: 2,
|
|
UserAllow: 3,
|
|
GuestAllow: 4,
|
|
Allow: 5,
|
|
}
|
|
|
|
scopeScore = map[TRbacScope]int{
|
|
ScopeNone: 0,
|
|
ScopeUser: 1,
|
|
ScopeProject: 2,
|
|
ScopeDomain: 3,
|
|
ScopeSystem: 4,
|
|
}
|
|
)
|
|
|
|
func (r TRbacResult) Strictness() int {
|
|
return strictness[r]
|
|
}
|
|
|
|
func (r1 TRbacResult) StricterThan(r2 TRbacResult) bool {
|
|
return r1.Strictness() < r2.Strictness()
|
|
}
|
|
|
|
func (r1 TRbacResult) LooserThan(r2 TRbacResult) bool {
|
|
return r1.Strictness() > r2.Strictness()
|
|
}
|
|
|
|
func (s1 TRbacScope) HigherEqual(s2 TRbacScope) bool {
|
|
return scopeScore[s1] >= scopeScore[s2]
|
|
}
|
|
|
|
func (s1 TRbacScope) HigherThan(s2 TRbacScope) bool {
|
|
return scopeScore[s1] > scopeScore[s2]
|
|
}
|
|
|
|
type SRbacPolicy struct {
|
|
// condition, when the policy takes effects
|
|
// Deprecated
|
|
Condition string
|
|
|
|
DomainId string
|
|
|
|
IsPublic bool
|
|
PublicScope TRbacScope
|
|
SharedDomainIds []string
|
|
|
|
Projects []string
|
|
Roles []string
|
|
Ips []netutils.IPV4Prefix
|
|
Auth bool // whether needs authentication
|
|
|
|
// scope, the scope of the policy, system/domain/project
|
|
Scope TRbacScope
|
|
// Deprecated
|
|
// is_admin=true means scope=system, is_admin=false means scope=project
|
|
IsAdmin bool
|
|
|
|
// rules, the exact rules
|
|
Rules []SRbacRule
|
|
}
|
|
|
|
type SRbacRule struct {
|
|
Service string
|
|
Resource string
|
|
Action string
|
|
Extra []string
|
|
Result TRbacResult
|
|
}
|
|
|
|
func (r SRbacRule) clone() SRbacRule {
|
|
nr := r
|
|
nr.Extra = make([]string, len(r.Extra))
|
|
if len(r.Extra) > 0 {
|
|
copy(nr.Extra, r.Extra)
|
|
}
|
|
return nr
|
|
}
|
|
|
|
func isWildMatch(str string) bool {
|
|
return len(str) == 0 || str == WILD_MATCH
|
|
}
|
|
|
|
func (rule *SRbacRule) contains(rule2 *SRbacRule) bool {
|
|
if !isWildMatch(rule.Service) && rule.Service != rule2.Service {
|
|
return false
|
|
}
|
|
if !isWildMatch(rule.Resource) && rule.Resource != rule2.Resource {
|
|
return false
|
|
}
|
|
if !isWildMatch(rule.Action) && rule.Action != rule2.Action {
|
|
return false
|
|
}
|
|
if len(rule.Extra) > 0 {
|
|
for i := 0; i < len(rule.Extra); i += 1 {
|
|
if !isWildMatch(rule.Extra[i]) && (rule2.Extra == nil || len(rule2.Extra) < i || rule.Extra[i] != rule2.Extra[i]) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
if string(rule.Result) != string(rule2.Result) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (rule *SRbacRule) stricterThan(r2 *SRbacRule) bool {
|
|
return rule.Result.StricterThan(r2.Result)
|
|
}
|
|
|
|
func (rule *SRbacRule) looserThan(r2 *SRbacRule) bool {
|
|
return rule.Result.LooserThan(r2.Result)
|
|
}
|
|
|
|
func (rule *SRbacRule) match(service string, resource string, action string, extra ...string) (bool, int, int) {
|
|
matched := 0
|
|
weight := 0
|
|
if !isWildMatch(rule.Service) {
|
|
if rule.Service != service {
|
|
return false, 0, 0
|
|
}
|
|
matched += 1
|
|
weight += 1
|
|
}
|
|
if !isWildMatch(rule.Resource) {
|
|
if rule.Resource != resource {
|
|
return false, 0, 0
|
|
}
|
|
matched += 1
|
|
weight += 10
|
|
}
|
|
if !isWildMatch(rule.Action) {
|
|
if rule.Action != action {
|
|
return false, 0, 0
|
|
}
|
|
matched += 1
|
|
weight += 100
|
|
}
|
|
for i := 0; i < len(rule.Extra) && i < len(extra); i += 1 {
|
|
if !isWildMatch(rule.Extra[i]) {
|
|
if rule.Extra[i] != extra[i] {
|
|
return false, 0, 0
|
|
}
|
|
matched += 1
|
|
weight += 1000 * (i + 1)
|
|
}
|
|
}
|
|
return true, matched, weight
|
|
}
|
|
|
|
func (policy *SRbacPolicy) getMatchRule(req []string) *SRbacRule {
|
|
service := WILD_MATCH
|
|
if len(req) > levelService {
|
|
service = req[levelService]
|
|
}
|
|
resource := WILD_MATCH
|
|
if len(req) > levelResource {
|
|
resource = req[levelResource]
|
|
}
|
|
action := WILD_MATCH
|
|
if len(req) > levelAction {
|
|
action = req[levelAction]
|
|
}
|
|
var extra []string
|
|
if len(req) > levelExtra {
|
|
extra = req[levelExtra:]
|
|
} else {
|
|
extra = make([]string, 0)
|
|
}
|
|
|
|
return policy.GetMatchRule(service, resource, action, extra...)
|
|
}
|
|
|
|
func (policy *SRbacPolicy) GetMatchRule(service string, resource string, action string, extra ...string) *SRbacRule {
|
|
return GetMatchRule(policy.Rules, service, resource, action, extra...)
|
|
}
|
|
|
|
var (
|
|
ShowMatchRuleDebug = false
|
|
)
|
|
|
|
func GetMatchRule(rules []SRbacRule, service string, resource string, action string, extra ...string) *SRbacRule {
|
|
maxMatchCnt := 0
|
|
minWeight := 1000000
|
|
var matchRule *SRbacRule
|
|
for i := 0; i < len(rules); i += 1 {
|
|
match, matchCnt, weight := rules[i].match(service, resource, action, extra...)
|
|
if match && ShowMatchRuleDebug {
|
|
log.Debugf("rule %s match cnt %d weight %d", rules[i], matchCnt, weight)
|
|
}
|
|
if match && (maxMatchCnt < matchCnt ||
|
|
(maxMatchCnt == matchCnt && minWeight > weight) ||
|
|
(maxMatchCnt == matchCnt && minWeight == weight && matchRule.stricterThan(&rules[i]))) {
|
|
maxMatchCnt = matchCnt
|
|
minWeight = weight
|
|
matchRule = &rules[i]
|
|
}
|
|
}
|
|
return matchRule
|
|
}
|
|
|
|
func CompactRules(rules []SRbacRule) []SRbacRule {
|
|
if len(rules) == 0 {
|
|
return nil
|
|
}
|
|
/*output := make([]SRbacRule, 1)
|
|
output[0] = rules[0]
|
|
for i := 1; i < len(rules); i += 1 {
|
|
isContains := false
|
|
for j := 0; j < len(output); j += 1 {
|
|
if output[j].contains(&rules[i]) {
|
|
isContains = true
|
|
break
|
|
}
|
|
if rules[i].contains(&output[j]) {
|
|
output[j] = rules[i]
|
|
isContains = true
|
|
break
|
|
}
|
|
}
|
|
if !isContains {
|
|
output = append(output, rules[i])
|
|
}
|
|
}*/
|
|
return reduceRules(rules)
|
|
}
|
|
|
|
var (
|
|
tenantEqualsPattern = regexp.MustCompile(`tenant\s*==\s*['"]?(\w+)['"]?`)
|
|
roleContainsPattern = regexp.MustCompile(`roles.contains\(['"]?(\w+)['"]?\)`)
|
|
)
|
|
|
|
func searchMatchStrings(pattern *regexp.Regexp, condstr string) []string {
|
|
ret := make([]string, 0)
|
|
matches := pattern.FindAllStringSubmatch(condstr, -1)
|
|
for _, match := range matches {
|
|
ret = append(ret, match[1])
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func searchMatchTenants(condstr string) []string {
|
|
return searchMatchStrings(tenantEqualsPattern, condstr)
|
|
}
|
|
|
|
func searchMatchRoles(condstr string) []string {
|
|
return searchMatchStrings(roleContainsPattern, condstr)
|
|
}
|
|
|
|
func (policy *SRbacPolicy) Decode(policyJson jsonutils.JSONObject) error {
|
|
policy.Condition, _ = policyJson.GetString("condition")
|
|
if policyJson.Contains("projects") {
|
|
projectJson, _ := policyJson.GetArray("projects")
|
|
policy.Projects = jsonutils.JSONArray2StringArray(projectJson)
|
|
}
|
|
if policyJson.Contains("roles") {
|
|
roleJson, _ := policyJson.GetArray("roles")
|
|
policy.Roles = jsonutils.JSONArray2StringArray(roleJson)
|
|
}
|
|
|
|
if len(policy.Projects) == 0 && len(policy.Roles) == 0 && len(policy.Condition) > 0 {
|
|
// XXX hack
|
|
// for smooth transtion from condition to projects&roles
|
|
policy.Projects = searchMatchTenants(policy.Condition)
|
|
policy.Roles = searchMatchRoles(policy.Condition)
|
|
}
|
|
// empty condition, no longer use this field
|
|
policy.Condition = ""
|
|
|
|
scopeStr, _ := policyJson.GetString("scope")
|
|
if len(scopeStr) > 0 {
|
|
policy.Scope = TRbacScope(scopeStr)
|
|
} else {
|
|
policy.IsAdmin = jsonutils.QueryBoolean(policyJson, "is_admin", false)
|
|
if len(policy.Scope) == 0 {
|
|
if policy.IsAdmin {
|
|
policy.Scope = ScopeSystem
|
|
} else {
|
|
policy.Scope = ScopeProject
|
|
}
|
|
}
|
|
}
|
|
|
|
if policyJson.Contains("ips") {
|
|
ipsJson, _ := policyJson.GetArray("ips")
|
|
ipStrs := jsonutils.JSONArray2StringArray(ipsJson)
|
|
policy.Ips = make([]netutils.IPV4Prefix, 0)
|
|
for _, ipStr := range ipStrs {
|
|
if len(ipStr) == 0 || ipStr == "0.0.0.0" {
|
|
continue
|
|
}
|
|
prefix, err := netutils.NewIPV4Prefix(ipStr)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
policy.Ips = append(policy.Ips, prefix)
|
|
}
|
|
}
|
|
|
|
policy.Auth = jsonutils.QueryBoolean(policyJson, "auth", true)
|
|
if len(policy.Ips) > 0 || len(policy.Roles) > 0 || len(policy.Projects) > 0 {
|
|
policy.Auth = true
|
|
}
|
|
|
|
ruleJson, err := policyJson.Get("policy")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
/*rules, err := decode(ruleJson, SRbacRule{}, levelService)*/
|
|
rules, err := json2Rules(ruleJson)
|
|
if err != nil {
|
|
return errors.Wrap(err, "json2Rules")
|
|
}
|
|
|
|
if len(rules) == 0 {
|
|
return ErrEmptyPolicy
|
|
}
|
|
|
|
policy.Rules = rules
|
|
|
|
return nil
|
|
}
|
|
|
|
const (
|
|
levelService = 0
|
|
levelResource = 1
|
|
levelAction = 2
|
|
levelExtra = 3
|
|
)
|
|
|
|
func decode(rules jsonutils.JSONObject, decodeRule SRbacRule, level int) ([]SRbacRule, error) {
|
|
switch rules.(type) {
|
|
case *jsonutils.JSONString:
|
|
ruleJsonStr := rules.(*jsonutils.JSONString)
|
|
ruleStr, _ := ruleJsonStr.GetString()
|
|
switch ruleStr {
|
|
case string(Allow), string(AdminAllow), string(OwnerAllow), string(UserAllow), string(GuestAllow):
|
|
decodeRule.Result = Allow
|
|
default:
|
|
decodeRule.Result = Deny
|
|
// default:
|
|
// return nil, fmt.Errorf("unsupported rule string %s", ruleStr)
|
|
}
|
|
return []SRbacRule{decodeRule}, nil
|
|
case *jsonutils.JSONDict:
|
|
ruleJsonDict, err := rules.GetMap()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "get rule map fail")
|
|
}
|
|
rules := make([]SRbacRule, 0)
|
|
for key, ruleJson := range ruleJsonDict {
|
|
rule := decodeRule
|
|
switch {
|
|
case level == levelService:
|
|
rule.Service = key
|
|
case level == levelResource:
|
|
rule.Resource = key
|
|
case level == levelAction:
|
|
rule.Action = key
|
|
case level >= levelExtra:
|
|
if rule.Extra == nil {
|
|
rule.Extra = make([]string, 1)
|
|
rule.Extra[0] = key
|
|
} else {
|
|
rule.Extra = append(rule.Extra, key)
|
|
}
|
|
}
|
|
decoded, err := decode(ruleJson, rule, level+1)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "decode")
|
|
}
|
|
rules = append(rules, decoded...)
|
|
}
|
|
return rules, nil
|
|
default:
|
|
return nil, errors.Wrap(ErrUnsuportRuleData, rules.String())
|
|
}
|
|
}
|
|
|
|
func (rule *SRbacRule) toStringArray() []string {
|
|
strArr := make([]string, 0)
|
|
strArr = append(strArr, rule.Service)
|
|
strArr = append(strArr, rule.Resource)
|
|
strArr = append(strArr, rule.Action)
|
|
if rule.Extra != nil {
|
|
strArr = append(strArr, rule.Extra...)
|
|
}
|
|
i := len(strArr) - 1
|
|
for i > 0 && (len(strArr[i]) == 0 || strArr[i] == WILD_MATCH) {
|
|
i -= 1
|
|
}
|
|
return strArr[0 : i+1]
|
|
}
|
|
|
|
func addRule2Json(nodeJson *jsonutils.JSONDict, keys []string, result TRbacResult) error {
|
|
if len(keys) == 1 {
|
|
if nodeJson.Contains(keys[0]) {
|
|
nextJson, _ := nodeJson.Get(keys[0])
|
|
switch nextJson.(type) {
|
|
case *jsonutils.JSONString: // conflict??
|
|
return ErrConflict // fmt.Errorf("conflict?")
|
|
case *jsonutils.JSONDict:
|
|
nextJsonDict := nextJson.(*jsonutils.JSONDict)
|
|
addRule2Json(nextJsonDict, []string{WILD_MATCH}, result)
|
|
return nil
|
|
default:
|
|
return ErrInvalidRules // fmt.Errorf("invalid rules")
|
|
}
|
|
} else {
|
|
nodeJson.Add(jsonutils.NewString(string(result)), keys[0])
|
|
return nil
|
|
}
|
|
}
|
|
// len(keys) > 1
|
|
exist, _ := nodeJson.Get(keys[0])
|
|
if exist != nil {
|
|
switch exist.(type) {
|
|
case *jsonutils.JSONString: // need restruct
|
|
newDict := jsonutils.NewDict()
|
|
newDict.Add(exist, "*")
|
|
nodeJson.Set(keys[0], newDict)
|
|
return addRule2Json(newDict, keys[1:], result)
|
|
case *jsonutils.JSONDict:
|
|
existDict := exist.(*jsonutils.JSONDict)
|
|
return addRule2Json(existDict, keys[1:], result)
|
|
default:
|
|
return ErrInvalidRules // fmt.Errorf("invalid rules")
|
|
}
|
|
} else {
|
|
next := jsonutils.NewDict()
|
|
nodeJson.Add(next, keys[0])
|
|
return addRule2Json(next, keys[1:], result)
|
|
}
|
|
}
|
|
|
|
func (policy *SRbacPolicy) Encode() (jsonutils.JSONObject, error) {
|
|
/*rules := jsonutils.NewDict()
|
|
for i := 0; i < len(policy.Rules); i += 1 {
|
|
keys := policy.Rules[i].toStringArray()
|
|
err := addRule2Json(rules, keys, policy.Rules[i].Result)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "addRule2Json")
|
|
}
|
|
}*/
|
|
|
|
rules := rules2Json(policy.Rules)
|
|
|
|
ret := jsonutils.NewDict()
|
|
// ret.Add(jsonutils.NewString(policy.Condition), "condition")
|
|
// if policy.IsAdmin {
|
|
// ret.Add(jsonutils.JSONTrue, "is_admin")
|
|
// } else {
|
|
// ret.Add(jsonutils.JSONFalse, "is_admin")
|
|
// }
|
|
|
|
ret.Add(jsonutils.NewString(string(policy.Scope)), "scope")
|
|
|
|
if !policy.Auth && len(policy.Projects) == 0 && len(policy.Roles) == 0 && len(policy.Ips) == 0 {
|
|
ret.Add(jsonutils.JSONFalse, "auth")
|
|
} else {
|
|
ret.Add(jsonutils.JSONTrue, "auth")
|
|
}
|
|
|
|
if len(policy.Projects) > 0 {
|
|
ret.Add(jsonutils.NewStringArray(policy.Projects), "projects")
|
|
}
|
|
if len(policy.Roles) > 0 {
|
|
ret.Add(jsonutils.NewStringArray(policy.Roles), "roles")
|
|
}
|
|
if len(policy.Ips) > 0 {
|
|
ipStrs := make([]string, len(policy.Ips))
|
|
for i := range policy.Ips {
|
|
ipStrs[i] = policy.Ips[i].String()
|
|
}
|
|
ret.Add(jsonutils.NewStringArray(ipStrs), "ips")
|
|
}
|
|
|
|
ret.Add(rules, "policy")
|
|
return ret, nil
|
|
}
|
|
|
|
func (policy *SRbacPolicy) Explain(request [][]string) [][]string {
|
|
output := make([][]string, len(request))
|
|
for i := 0; i < len(request); i += 1 {
|
|
rule := policy.getMatchRule(request[i])
|
|
if rule == nil {
|
|
output[i] = append(request[i], string(Deny))
|
|
} else {
|
|
output[i] = append(request[i], string(rule.Result))
|
|
}
|
|
}
|
|
return output
|
|
}
|
|
|
|
func contains(s1 []string, s string) bool {
|
|
for i := range s1 {
|
|
if s1[i] == s {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func intersect(s1 []string, s2 []string) bool {
|
|
for i := range s1 {
|
|
for j := range s2 {
|
|
if s1[i] == s2[j] {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func containsIp(ips []netutils.IPV4Prefix, ipStr string) bool {
|
|
if len(ipStr) == 0 {
|
|
// user comes from unknown ip, assume matches
|
|
return true
|
|
}
|
|
ip, err := netutils.NewIPV4Addr(ipStr)
|
|
if err != nil {
|
|
log.Errorf("user comes from invalid ipv4 addr %s: %s", ipStr, err)
|
|
return false
|
|
}
|
|
for i := range ips {
|
|
if ips[i].Contains(ip) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
type IRbacIdentity interface {
|
|
GetProjectDomainId() string
|
|
GetProjectName() string
|
|
GetRoles() []string
|
|
GetLoginIp() string
|
|
GetTokenString() string
|
|
}
|
|
|
|
func (policy *SRbacPolicy) IsSystemWidePolicy() bool {
|
|
return (len(policy.DomainId) == 0 || (policy.IsPublic && policy.PublicScope == ScopeSystem)) && len(policy.Roles) == 0 && len(policy.Projects) == 0
|
|
}
|
|
|
|
func (policy *SRbacPolicy) MatchDomain(domainId string) bool {
|
|
if len(policy.DomainId) == 0 || len(domainId) == 0 {
|
|
return true
|
|
}
|
|
if policy.DomainId == domainId {
|
|
return true
|
|
}
|
|
if policy.IsPublic {
|
|
if policy.PublicScope == ScopeSystem {
|
|
return true
|
|
}
|
|
if contains(policy.SharedDomainIds, domainId) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (policy *SRbacPolicy) MatchProject(projectName string) bool {
|
|
if len(policy.Projects) == 0 || len(projectName) == 0 {
|
|
return true
|
|
}
|
|
if contains(policy.Projects, projectName) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (policy *SRbacPolicy) MatchRoles(roleNames []string) bool {
|
|
if len(policy.Roles) == 0 {
|
|
return true
|
|
}
|
|
if intersect(policy.Roles, roleNames) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// check whether policy maches a userCred
|
|
// return value
|
|
// bool isMatched
|
|
// int match weight, the higher the value, the more exact the match
|
|
// the more exact match wins
|
|
func (policy *SRbacPolicy) Match(userCred IRbacIdentity) (bool, int) {
|
|
if !policy.Auth && len(policy.Roles) == 0 && len(policy.Projects) == 0 && len(policy.Ips) == 0 {
|
|
return true, 1
|
|
}
|
|
if userCred == nil || len(userCred.GetTokenString()) == 0 {
|
|
return false, 0
|
|
}
|
|
weight := 0
|
|
if policy.MatchDomain(userCred.GetProjectDomainId()) {
|
|
if len(policy.DomainId) > 0 {
|
|
if policy.DomainId == userCred.GetProjectDomainId() {
|
|
weight += 30 // exact domain match
|
|
} else if len(policy.SharedDomainIds) > 0 {
|
|
weight += 20 // shared domain match
|
|
} else {
|
|
weight += 10 // else, system scope match
|
|
}
|
|
}
|
|
if policy.MatchRoles(userCred.GetRoles()) {
|
|
if len(policy.Roles) != 0 {
|
|
weight += 100
|
|
}
|
|
if policy.MatchProject(userCred.GetProjectName()) {
|
|
if len(policy.Projects) > 0 {
|
|
weight += 1000
|
|
}
|
|
if len(policy.Ips) == 0 || containsIp(policy.Ips, userCred.GetLoginIp()) {
|
|
if len(policy.Ips) > 0 {
|
|
weight += 10000
|
|
}
|
|
return true, weight
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false, 0
|
|
}
|
|
|
|
type sSimpleRbacIdentity struct {
|
|
domainId string
|
|
projectName string
|
|
roleNames []string
|
|
}
|
|
|
|
func (id sSimpleRbacIdentity) GetProjectDomainId() string {
|
|
return id.domainId
|
|
}
|
|
|
|
func (id sSimpleRbacIdentity) GetRoles() []string {
|
|
return id.roleNames
|
|
}
|
|
|
|
func (id sSimpleRbacIdentity) GetProjectName() string {
|
|
return id.projectName
|
|
}
|
|
|
|
func (id sSimpleRbacIdentity) GetLoginIp() string {
|
|
return ""
|
|
}
|
|
|
|
func (id sSimpleRbacIdentity) GetTokenString() string {
|
|
return "faketoken"
|
|
}
|
|
|
|
func NewRbacIdentity(domainId, projectName string, roleNames []string) IRbacIdentity {
|
|
return sSimpleRbacIdentity{
|
|
domainId: domainId,
|
|
projectName: projectName,
|
|
roleNames: roleNames,
|
|
}
|
|
}
|
|
|
|
func String2Scope(str string) TRbacScope {
|
|
return String2ScopeDefault(str, ScopeProject)
|
|
}
|
|
|
|
func String2ScopeDefault(str string, defScope TRbacScope) TRbacScope {
|
|
switch strings.ToLower(str) {
|
|
case string(ScopeSystem):
|
|
return ScopeSystem
|
|
case string(ScopeDomain):
|
|
return ScopeDomain
|
|
case string(ScopeProject):
|
|
return ScopeProject
|
|
case string(ScopeUser):
|
|
return ScopeUser
|
|
case "true":
|
|
return ScopeSystem
|
|
default:
|
|
return defScope
|
|
}
|
|
}
|