Files
kubesphere/pkg/models/iam/am/am.go
hongming a3d3c8e427 update
Signed-off-by: hongming <talonwan@yunify.com>
2020-04-10 15:41:23 +08:00

136 lines
3.8 KiB
Go

/*
*
* 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 am
import (
"fmt"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/klog"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"net/http"
)
type AccessManagementInterface interface {
ListRolesOfUser(scope iamv1alpha2.Scope, username string) ([]iamv1alpha2.Role, error)
GetRoleOfUserInTargetScope(scope iamv1alpha2.Scope, target string, username string) (*iamv1alpha2.Role, error)
GetPolicyRule(name string) (*iamv1alpha2.PolicyRule, error)
}
type amOperator struct {
informers informers.SharedInformerFactory
ksClient kubesphere.Interface
}
func NewAMOperator(ksClient kubesphere.Interface, informers informers.SharedInformerFactory) AccessManagementInterface {
return &amOperator{
informers: informers,
ksClient: ksClient,
}
}
func containsUser(subjets []iamv1alpha2.Subject, username string) bool {
for _, sub := range subjets {
if sub.Kind == iamv1alpha2.UserKind && sub.Name == username {
return true
}
}
return false
}
func (am *amOperator) ListRolesOfUser(scope iamv1alpha2.Scope, username string) ([]iamv1alpha2.Role, error) {
lister := am.informers.Iam().V1alpha2().RoleBindings().Lister()
roleBindings, err := lister.List(labels.Everything())
if err != nil {
klog.Error(err)
return nil, err
}
roleBindingsInScope := filterRoleBindingByScope(roleBindings, scope)
roles := make([]iamv1alpha2.Role, 0)
for _, roleBinding := range roleBindingsInScope {
if containsUser(roleBinding.Subjects, username) {
role, err := am.informers.
Iam().V1alpha2().Roles().Lister().Get(roleBinding.RoleRef.Name)
if err != nil {
if errors.IsNotFound(err) {
continue
}
return nil, err
}
roles = append(roles, *role)
}
}
return roles, nil
}
func filterRoleBindingByScope(roles []*iamv1alpha2.RoleBinding, scope iamv1alpha2.Scope) []*iamv1alpha2.RoleBinding {
result := make([]*iamv1alpha2.RoleBinding, 0)
for _, role := range roles {
if role.Scope == scope {
result = append(result, role)
}
}
return result
}
func (am *amOperator) GetPolicyRule(name string) (*iamv1alpha2.PolicyRule, error) {
lister := am.informers.Iam().V1alpha2().PolicyRules().Lister()
return lister.Get(name)
}
// Users can only bind one role at each level
func (am *amOperator) GetRoleOfUserInTargetScope(scope iamv1alpha2.Scope, target, username string) (*iamv1alpha2.Role, error) {
roles, err := am.ListRolesOfUser(scope, username)
if err != nil {
klog.Error(err)
return nil, err
}
for _, role := range roles {
if role.Target.Name == iamv1alpha2.TargetAll ||
role.Target.Name == target {
return &role, nil
}
}
err = &errors.StatusError{ErrStatus: metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusNotFound,
Reason: metav1.StatusReasonNotFound,
Details: &metav1.StatusDetails{
Group: iamv1alpha2.SchemeGroupVersion.Group,
Kind: iamv1alpha2.RoleBindingKind,
},
Message: fmt.Sprintf("role bind not found in %s %s scope", target, scope),
}}
klog.Error(err)
return nil, err
}