@@ -1,175 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 The KubeSphere Authors.
|
||||
*
|
||||
* 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 authorizerfactory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/open-policy-agent/opa/rego"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/klog"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
)
|
||||
|
||||
type opaAuthorizer struct {
|
||||
am am.AccessManagementInterface
|
||||
}
|
||||
|
||||
const (
|
||||
defaultRegoQuery = "data.authz.allow"
|
||||
)
|
||||
|
||||
// Make decision by request attributes
|
||||
func (o *opaAuthorizer) Authorize(attr authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||
// Make decisions based on the authorization policy of different levels of roles
|
||||
// Error returned when an internal error occurs
|
||||
// Reason must be returned when access is denied
|
||||
globalRole, err := o.am.GetGlobalRoleOfUser(attr.GetUser().GetName())
|
||||
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
return authorizer.DecisionNoOpinion, "", err
|
||||
}
|
||||
|
||||
// check global policy rules
|
||||
if authorized, reason, err = o.makeDecision(globalRole, attr); authorized == authorizer.DecisionAllow {
|
||||
return authorized, reason, nil
|
||||
}
|
||||
|
||||
// it's global resource, permission denied
|
||||
if attr.GetResourceScope() == iamv1alpha2.GlobalScope {
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
|
||||
if attr.GetResourceScope() == iamv1alpha2.WorkspaceScope {
|
||||
workspaceRole, err := o.am.GetWorkspaceRoleOfUser(attr.GetUser().GetName(), attr.GetWorkspace())
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
return authorizer.DecisionNoOpinion, "", err
|
||||
}
|
||||
|
||||
// check workspace role policy rules
|
||||
if authorized, reason, err := o.makeDecision(workspaceRole, attr); authorized == authorizer.DecisionAllow {
|
||||
return authorized, reason, err
|
||||
} else if err != nil {
|
||||
return authorizer.DecisionNoOpinion, "", err
|
||||
}
|
||||
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
|
||||
if attr.GetResourceScope() == iamv1alpha2.NamespaceScope {
|
||||
role, err := o.am.GetNamespaceRoleOfUser(attr.GetUser().GetName(), attr.GetNamespace())
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
return authorizer.DecisionNoOpinion, "", err
|
||||
}
|
||||
// check namespace role policy rules
|
||||
if authorized, reason, err := o.makeDecision(role, attr); authorized == authorizer.DecisionAllow {
|
||||
return authorized, reason, err
|
||||
} else if err != nil {
|
||||
return authorizer.DecisionNoOpinion, "", err
|
||||
}
|
||||
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
|
||||
clusterRole, err := o.am.GetClusterRoleOfUser(attr.GetUser().GetName(), attr.GetCluster())
|
||||
|
||||
if errors.IsNotFound(err) {
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return authorizer.DecisionNoOpinion, "", err
|
||||
}
|
||||
|
||||
// check cluster role policy rules
|
||||
if authorized, reason, err := o.makeDecision(clusterRole, attr); authorized == authorizer.DecisionAllow {
|
||||
return authorized, reason, nil
|
||||
} else if err != nil {
|
||||
return authorizer.DecisionNoOpinion, "", err
|
||||
}
|
||||
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
|
||||
// Make decision base on role
|
||||
func (o *opaAuthorizer) makeDecision(role interface{}, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||
|
||||
regoPolicy := ""
|
||||
|
||||
// override
|
||||
if globalRole, ok := role.(*iamv1alpha2.GlobalRole); ok {
|
||||
if overrideRego, ok := globalRole.Annotations[iamv1alpha2.RegoOverrideAnnotation]; ok {
|
||||
regoPolicy = overrideRego
|
||||
}
|
||||
} else if workspaceRole, ok := role.(*iamv1alpha2.WorkspaceRole); ok {
|
||||
if overrideRego, ok := workspaceRole.Annotations[iamv1alpha2.RegoOverrideAnnotation]; ok {
|
||||
regoPolicy = overrideRego
|
||||
}
|
||||
} else if clusterRole, ok := role.(*rbacv1.ClusterRole); ok {
|
||||
if overrideRego, ok := clusterRole.Annotations[iamv1alpha2.RegoOverrideAnnotation]; ok {
|
||||
regoPolicy = overrideRego
|
||||
}
|
||||
} else if role, ok := role.(*rbacv1.Role); ok {
|
||||
if overrideRego, ok := role.Annotations[iamv1alpha2.RegoOverrideAnnotation]; ok {
|
||||
regoPolicy = overrideRego
|
||||
}
|
||||
}
|
||||
|
||||
if regoPolicy == "" {
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
|
||||
// Call the rego.New function to create an object that can be prepared or evaluated
|
||||
// After constructing a new rego.Rego object you can call PrepareForEval() to obtain an executable query
|
||||
query, err := rego.New(rego.Query(defaultRegoQuery), rego.Module("authz.rego", regoPolicy)).PrepareForEval(context.Background())
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("syntax error:%s,refer: %s+v", err, role)
|
||||
return authorizer.DecisionNoOpinion, "", err
|
||||
}
|
||||
|
||||
// The policy decision is contained in the results returned by the Eval() call. You can inspect the decision and handle it accordingly.
|
||||
results, err := query.Eval(context.Background(), rego.EvalInput(a))
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("syntax error:%s,refer: %s+v", err, role)
|
||||
return authorizer.DecisionNoOpinion, "", err
|
||||
}
|
||||
|
||||
if len(results) > 0 && results[0].Expressions[0].Value == true {
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
||||
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
|
||||
func NewOPAAuthorizer(am am.AccessManagementInterface) *opaAuthorizer {
|
||||
return &opaAuthorizer{am: am}
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 The KubeSphere Authors.
|
||||
*
|
||||
* 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 authorizerfactory
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
fakek8s "k8s.io/client-go/kubernetes/fake"
|
||||
iamvealpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
|
||||
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
|
||||
factory "kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGlobalRole(t *testing.T) {
|
||||
|
||||
operator, err := prepare()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
opa := NewOPAAuthorizer(operator)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
request authorizer.AttributesRecord
|
||||
expectedDecision authorizer.Decision
|
||||
}{
|
||||
{
|
||||
name: "admin can list nodes",
|
||||
request: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "admin",
|
||||
UID: "0",
|
||||
Groups: []string{"admin"},
|
||||
Extra: nil,
|
||||
},
|
||||
Verb: "list",
|
||||
APIVersion: "v1",
|
||||
Resource: "nodes",
|
||||
KubernetesRequest: true,
|
||||
ResourceRequest: true,
|
||||
Path: "/api/v1/nodes",
|
||||
},
|
||||
expectedDecision: authorizer.DecisionAllow,
|
||||
},
|
||||
{
|
||||
name: "anonymous can not list nodes",
|
||||
request: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: user.Anonymous,
|
||||
UID: "0",
|
||||
Groups: []string{"admin"},
|
||||
Extra: nil,
|
||||
},
|
||||
Verb: "list",
|
||||
APIVersion: "v1",
|
||||
Resource: "nodes",
|
||||
KubernetesRequest: true,
|
||||
ResourceRequest: true,
|
||||
Path: "/api/v1/nodes",
|
||||
},
|
||||
expectedDecision: authorizer.DecisionNoOpinion,
|
||||
}, {
|
||||
name: "tom can list nodes in cluster1",
|
||||
request: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "tom",
|
||||
},
|
||||
Verb: "list",
|
||||
Cluster: "cluster1",
|
||||
APIVersion: "v1",
|
||||
Resource: "nodes",
|
||||
KubernetesRequest: true,
|
||||
ResourceRequest: true,
|
||||
Path: "/api/v1/clusters/cluster1/nodes",
|
||||
},
|
||||
expectedDecision: authorizer.DecisionAllow,
|
||||
},
|
||||
{
|
||||
name: "tom can not list nodes in cluster2",
|
||||
request: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "tom",
|
||||
},
|
||||
Verb: "list",
|
||||
Cluster: "cluster2",
|
||||
APIVersion: "v1",
|
||||
Resource: "nodes",
|
||||
KubernetesRequest: true,
|
||||
ResourceRequest: true,
|
||||
Path: "/api/v1/clusters/cluster2/nodes",
|
||||
},
|
||||
expectedDecision: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
decision, _, err := opa.Authorize(test.request)
|
||||
if err != nil {
|
||||
t.Errorf("test failed: %s, %v", test.name, err)
|
||||
}
|
||||
if decision != test.expectedDecision {
|
||||
t.Errorf("%s: expected decision %v, actual %+v", test.name, test.expectedDecision, decision)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func prepare() (am.AccessManagementInterface, error) {
|
||||
globalRoles := []*iamvealpha2.GlobalRole{
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: iamvealpha2.ResourceKindGlobalRole,
|
||||
APIVersion: iamvealpha2.SchemeGroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "global-admin",
|
||||
Annotations: map[string]string{iamvealpha2.RegoOverrideAnnotation: "package authz\ndefault allow = true"},
|
||||
},
|
||||
}, {
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: iamvealpha2.ResourceKindGlobalRole,
|
||||
APIVersion: iamvealpha2.SchemeGroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "anonymous",
|
||||
Annotations: map[string]string{iamvealpha2.RegoOverrideAnnotation: "package authz\ndefault allow = false"},
|
||||
},
|
||||
}, {
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: iamvealpha2.ResourceKindGlobalRole,
|
||||
APIVersion: iamvealpha2.SchemeGroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster1-admin",
|
||||
Annotations: map[string]string{iamvealpha2.RegoOverrideAnnotation: `package authz
|
||||
default allow = false
|
||||
allow {
|
||||
resources_in_cluster1
|
||||
}
|
||||
resources_in_cluster1 {
|
||||
input.Cluster == "cluster1"
|
||||
}`},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
roleBindings := []*iamvealpha2.GlobalRoleBinding{
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: iamvealpha2.ResourceKindGlobalRoleBinding,
|
||||
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "global-admin",
|
||||
},
|
||||
RoleRef: rbacv1.RoleRef{
|
||||
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
|
||||
Kind: iamvealpha2.ResourceKindGlobalRole,
|
||||
Name: "global-admin",
|
||||
},
|
||||
Subjects: []rbacv1.Subject{
|
||||
{
|
||||
Kind: iamvealpha2.ResourceKindUser,
|
||||
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
|
||||
Name: "admin",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: iamvealpha2.ResourceKindGlobalRoleBinding,
|
||||
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "anonymous",
|
||||
},
|
||||
RoleRef: rbacv1.RoleRef{
|
||||
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
|
||||
Kind: iamvealpha2.ResourceKindGlobalRole,
|
||||
Name: "anonymous",
|
||||
},
|
||||
Subjects: []rbacv1.Subject{
|
||||
{
|
||||
Kind: iamvealpha2.ResourceKindUser,
|
||||
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
|
||||
Name: user.Anonymous,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: iamvealpha2.ResourceKindGlobalRoleBinding,
|
||||
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster1-admin",
|
||||
},
|
||||
RoleRef: rbacv1.RoleRef{
|
||||
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
|
||||
Kind: iamvealpha2.ResourceKindGlobalRole,
|
||||
Name: "cluster1-admin",
|
||||
},
|
||||
Subjects: []rbacv1.Subject{
|
||||
{
|
||||
Kind: iamvealpha2.ResourceKindUser,
|
||||
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
|
||||
Name: "tom",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ksClient := fake.NewSimpleClientset()
|
||||
k8sClient := fakek8s.NewSimpleClientset()
|
||||
factory := factory.NewInformerFactories(k8sClient, ksClient, nil, nil, nil, nil)
|
||||
for _, role := range globalRoles {
|
||||
err := factory.KubeSphereSharedInformerFactory().Iam().V1alpha2().GlobalRoles().Informer().GetIndexer().Add(role)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("add role:%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, roleBinding := range roleBindings {
|
||||
err := factory.KubeSphereSharedInformerFactory().Iam().V1alpha2().GlobalRoleBindings().Informer().GetIndexer().Add(roleBinding)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("add role binding:%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
operator := am.NewAMOperator(factory)
|
||||
|
||||
return operator, nil
|
||||
}
|
||||
@@ -20,10 +20,13 @@ package authorizerfactory
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/open-policy-agent/opa/rego"
|
||||
"k8s.io/apiserver/pkg/authentication/serviceaccount"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/request"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
|
||||
@@ -35,6 +38,11 @@ import (
|
||||
rbacv1helpers "kubesphere.io/kubesphere/pkg/apis/rbac/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultRegoQuery = "data.authz.allow"
|
||||
defaultRegoFileName = "authz.rego"
|
||||
)
|
||||
|
||||
type RBACAuthorizer struct {
|
||||
am am.AccessManagementInterface
|
||||
}
|
||||
@@ -48,7 +56,12 @@ type authorizingVisitor struct {
|
||||
errors []error
|
||||
}
|
||||
|
||||
func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool {
|
||||
func (v *authorizingVisitor) visit(source fmt.Stringer, regoPolicy string, rule *rbacv1.PolicyRule, err error) bool {
|
||||
if regoPolicy != "" && regoPolicyAllows(v.requestAttributes, regoPolicy) {
|
||||
v.allowed = true
|
||||
v.reason = fmt.Sprintf("RBAC: allowed by %s", source.String())
|
||||
return false
|
||||
}
|
||||
if rule != nil && ruleAllows(v.requestAttributes, rule) {
|
||||
v.allowed = true
|
||||
v.reason = fmt.Sprintf("RBAC: allowed by %s", source.String())
|
||||
@@ -65,7 +78,7 @@ type ruleAccumulator struct {
|
||||
errors []error
|
||||
}
|
||||
|
||||
func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool {
|
||||
func (r *ruleAccumulator) visit(source fmt.Stringer, _ string, rule *rbacv1.PolicyRule, err error) bool {
|
||||
if rule != nil {
|
||||
r.rules = append(r.rules, *rule)
|
||||
}
|
||||
@@ -155,15 +168,40 @@ func ruleAllows(requestAttributes authorizer.Attributes, rule *rbacv1.PolicyRule
|
||||
rbacv1helpers.NonResourceURLMatches(rule, requestAttributes.GetPath())
|
||||
}
|
||||
|
||||
func regoPolicyAllows(requestAttributes authorizer.Attributes, regoPolicy string) bool {
|
||||
// Call the rego.New function to create an object that can be prepared or evaluated
|
||||
// After constructing a new rego.Rego object you can call PrepareForEval() to obtain an executable query
|
||||
query, err := rego.New(rego.Query(defaultRegoQuery), rego.Module(defaultRegoFileName, regoPolicy)).PrepareForEval(context.Background())
|
||||
|
||||
if err != nil {
|
||||
klog.Warningf("syntax error:%s, content: %s", err, regoPolicy)
|
||||
return false
|
||||
}
|
||||
|
||||
// The policy decision is contained in the results returned by the Eval() call. You can inspect the decision and handle it accordingly.
|
||||
results, err := query.Eval(context.Background(), rego.EvalInput(requestAttributes))
|
||||
|
||||
if err != nil {
|
||||
klog.Warningf("syntax error:%s, content: %s", err, regoPolicy)
|
||||
return false
|
||||
}
|
||||
|
||||
if len(results) > 0 && results[0].Expressions[0].Value == true {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *RBACAuthorizer) rulesFor(requestAttributes authorizer.Attributes) ([]rbacv1.PolicyRule, error) {
|
||||
visitor := &ruleAccumulator{}
|
||||
r.visitRulesFor(requestAttributes, visitor.visit)
|
||||
return visitor.rules, utilerrors.NewAggregate(visitor.errors)
|
||||
}
|
||||
|
||||
func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool) {
|
||||
func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes, visitor func(source fmt.Stringer, regoPolicy string, rule *rbacv1.PolicyRule, err error) bool) {
|
||||
if globalRoleBindings, err := r.am.ListGlobalRoleBindings(""); err != nil {
|
||||
if !visitor(nil, nil, err) {
|
||||
if !visitor(nil, "", nil, err) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -173,26 +211,27 @@ func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes,
|
||||
if !applies {
|
||||
continue
|
||||
}
|
||||
rules, err := r.am.GetRoleReferenceRules(globalRoleBinding.RoleRef, "")
|
||||
regoPolicy, rules, err := r.am.GetRoleReferenceRules(globalRoleBinding.RoleRef, "")
|
||||
if err != nil {
|
||||
if !visitor(nil, nil, err) {
|
||||
return
|
||||
}
|
||||
visitor(nil, "", nil, err)
|
||||
continue
|
||||
}
|
||||
sourceDescriber.binding = globalRoleBinding
|
||||
sourceDescriber.subject = &globalRoleBinding.Subjects[subjectIndex]
|
||||
if !visitor(sourceDescriber, regoPolicy, nil, nil) {
|
||||
return
|
||||
}
|
||||
for i := range rules {
|
||||
if !visitor(sourceDescriber, &rules[i], nil) {
|
||||
if !visitor(sourceDescriber, "", &rules[i], nil) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if requestAttributes.GetResourceScope() == iamv1alpha2.WorkspaceScope {
|
||||
if requestAttributes.GetResourceScope() == request.WorkspaceScope {
|
||||
if workspaceRoleBindings, err := r.am.ListWorkspaceRoleBindings("", requestAttributes.GetWorkspace()); err != nil {
|
||||
if !visitor(nil, nil, err) {
|
||||
if !visitor(nil, "", nil, err) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -202,17 +241,18 @@ func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes,
|
||||
if !applies {
|
||||
continue
|
||||
}
|
||||
rules, err := r.am.GetRoleReferenceRules(workspaceRoleBinding.RoleRef, "")
|
||||
regoPolicy, rules, err := r.am.GetRoleReferenceRules(workspaceRoleBinding.RoleRef, "")
|
||||
if err != nil {
|
||||
if !visitor(nil, nil, err) {
|
||||
return
|
||||
}
|
||||
visitor(nil, "", nil, err)
|
||||
continue
|
||||
}
|
||||
sourceDescriber.binding = workspaceRoleBinding
|
||||
sourceDescriber.subject = &workspaceRoleBinding.Subjects[subjectIndex]
|
||||
if !visitor(sourceDescriber, regoPolicy, nil, nil) {
|
||||
return
|
||||
}
|
||||
for i := range rules {
|
||||
if !visitor(sourceDescriber, &rules[i], nil) {
|
||||
if !visitor(sourceDescriber, "", &rules[i], nil) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -220,9 +260,9 @@ func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes,
|
||||
}
|
||||
}
|
||||
|
||||
if requestAttributes.GetResourceScope() == iamv1alpha2.NamespaceScope {
|
||||
if requestAttributes.GetResourceScope() == request.NamespaceScope {
|
||||
if roleBindings, err := r.am.ListRoleBindings("", requestAttributes.GetNamespace()); err != nil {
|
||||
if !visitor(nil, nil, err) {
|
||||
if !visitor(nil, "", nil, err) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -232,17 +272,18 @@ func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes,
|
||||
if !applies {
|
||||
continue
|
||||
}
|
||||
rules, err := r.am.GetRoleReferenceRules(roleBinding.RoleRef, requestAttributes.GetNamespace())
|
||||
regoPolicy, rules, err := r.am.GetRoleReferenceRules(roleBinding.RoleRef, requestAttributes.GetNamespace())
|
||||
if err != nil {
|
||||
if !visitor(nil, nil, err) {
|
||||
return
|
||||
}
|
||||
visitor(nil, "", nil, err)
|
||||
continue
|
||||
}
|
||||
sourceDescriber.binding = roleBinding
|
||||
sourceDescriber.subject = &roleBinding.Subjects[subjectIndex]
|
||||
if !visitor(sourceDescriber, regoPolicy, nil, nil) {
|
||||
return
|
||||
}
|
||||
for i := range rules {
|
||||
if !visitor(sourceDescriber, &rules[i], nil) {
|
||||
if !visitor(sourceDescriber, "", &rules[i], nil) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -251,7 +292,7 @@ func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes,
|
||||
}
|
||||
|
||||
if clusterRoleBindings, err := r.am.ListClusterRoleBindings(""); err != nil {
|
||||
if !visitor(nil, nil, err) {
|
||||
if !visitor(nil, "", nil, err) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -261,17 +302,18 @@ func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes,
|
||||
if !applies {
|
||||
continue
|
||||
}
|
||||
rules, err := r.am.GetRoleReferenceRules(clusterRoleBinding.RoleRef, "")
|
||||
regoPolicy, rules, err := r.am.GetRoleReferenceRules(clusterRoleBinding.RoleRef, "")
|
||||
if err != nil {
|
||||
if !visitor(nil, nil, err) {
|
||||
return
|
||||
}
|
||||
visitor(nil, "", nil, err)
|
||||
continue
|
||||
}
|
||||
sourceDescriber.binding = clusterRoleBinding
|
||||
sourceDescriber.subject = &clusterRoleBinding.Subjects[subjectIndex]
|
||||
if !visitor(sourceDescriber, regoPolicy, nil, nil) {
|
||||
return
|
||||
}
|
||||
for i := range rules {
|
||||
if !visitor(sourceDescriber, &rules[i], nil) {
|
||||
if !visitor(sourceDescriber, "", &rules[i], nil) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ import (
|
||||
"io"
|
||||
fakeistio "istio.io/client-go/pkg/clientset/versioned/fake"
|
||||
fakek8s "k8s.io/client-go/kubernetes/fake"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/request"
|
||||
fakeks "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
@@ -208,10 +208,10 @@ func TestRBACAuthorizer(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
scope := iamv1alpha2.ClusterScope
|
||||
scope := request.ClusterScope
|
||||
|
||||
if tc.namespace != "" {
|
||||
scope = iamv1alpha2.NamespaceScope
|
||||
scope = request.NamespaceScope
|
||||
}
|
||||
|
||||
rules, err := ruleResolver.rulesFor(authorizer.AttributesRecord{
|
||||
@@ -274,7 +274,7 @@ func newMockRBACAuthorizer(staticRoles *StaticRoles) (*RBACAuthorizer, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return NewRBACAuthorizer(am.NewAMOperator(fakeInformerFactory)), nil
|
||||
return NewRBACAuthorizer(am.NewReadOnlyOperator(fakeInformerFactory)), nil
|
||||
}
|
||||
|
||||
func TestAppliesTo(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user