Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-03-19 22:44:05 +08:00
parent 23f6be88c6
commit 9769357005
332 changed files with 69808 additions and 4129 deletions

View File

@@ -1,606 +0,0 @@
/*
Copyright 2019 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 iam
import (
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam/policy"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/clusterrole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/resource"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/role"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
)
const (
ClusterRoleKind = "ClusterRole"
NamespaceAdminRoleBindName = "admin"
NamespaceViewerRoleBindName = "viewer"
)
type AccessManagementInterface interface {
GetClusterRole(username string) (*rbacv1.ClusterRole, error)
UnBindAllRoles(username string) error
ListRoleBindings(namespace string, role string) ([]*rbacv1.RoleBinding, error)
CreateClusterRoleBinding(username string, clusterRole string) error
ListRoles(namespace string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
ListClusterRoles(conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
ListClusterRoleBindings(clusterRole string) ([]*rbacv1.ClusterRoleBinding, error)
GetClusterRoleSimpleRules(clusterRole string) ([]policy.SimpleRule, error)
GetRoleSimpleRules(namespace string, role string) ([]policy.SimpleRule, error)
GetRoles(namespace, username string) ([]*rbacv1.Role, error)
GetClusterPolicyRules(username string) ([]rbacv1.PolicyRule, error)
GetPolicyRules(namespace, username string) ([]rbacv1.PolicyRule, error)
GetWorkspaceRoleSimpleRules(workspace, roleName string) []policy.SimpleRule
GetWorkspaceRole(workspace, username string) (*rbacv1.ClusterRole, error)
GetWorkspaceRoleMap(username string) (map[string]string, error)
}
type amOperator struct {
informers informers.SharedInformerFactory
resources resource.ResourceGetter
kubeClient kubernetes.Interface
}
func (am *amOperator) ListClusterRoleBindings(clusterRole string) ([]*rbacv1.ClusterRoleBinding, error) {
panic("implement me")
}
func (am *amOperator) GetRoles(namespace, username string) ([]*rbacv1.Role, error) {
panic("implement me")
}
func (am *amOperator) GetClusterPolicyRules(username string) ([]rbacv1.PolicyRule, error) {
panic("implement me")
}
func (am *amOperator) GetPolicyRules(namespace, username string) ([]rbacv1.PolicyRule, error) {
panic("implement me")
}
func (am *amOperator) GetWorkspaceRole(workspace, username string) (*rbacv1.ClusterRole, error) {
panic("implement me")
}
func (am *amOperator) UnBindAllRoles(username string) error {
panic("implement me")
}
func NewAMOperator(kubeClient kubernetes.Interface, informers informers.SharedInformerFactory) *amOperator {
resourceGetter := resource.ResourceGetter{}
resourceGetter.Add(v1alpha2.Role, role.NewRoleSearcher(informers))
resourceGetter.Add(v1alpha2.ClusterRoles, clusterrole.NewClusterRoleSearcher(informers))
return &amOperator{
informers: informers,
resources: resourceGetter,
kubeClient: kubeClient,
}
}
func (am *amOperator) GetDevopsRoleSimpleRules(role string) []policy.SimpleRule {
var rules []policy.SimpleRule
switch role {
case "developer":
rules = []policy.SimpleRule{
{Name: "pipelines", Actions: []string{"view", "trigger"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "members", Actions: []string{"view"}},
{Name: "devops", Actions: []string{"view"}},
}
break
case "owner":
rules = []policy.SimpleRule{
{Name: "pipelines", Actions: []string{"create", "edit", "view", "delete", "trigger"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "members", Actions: []string{"create", "edit", "view", "delete"}},
{Name: "credentials", Actions: []string{"create", "edit", "view", "delete"}},
{Name: "devops", Actions: []string{"edit", "view", "delete"}},
}
break
case "maintainer":
rules = []policy.SimpleRule{
{Name: "pipelines", Actions: []string{"create", "edit", "view", "delete", "trigger"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "members", Actions: []string{"view"}},
{Name: "credentials", Actions: []string{"create", "edit", "view", "delete"}},
{Name: "devops", Actions: []string{"view"}},
}
break
case "reporter":
fallthrough
default:
rules = []policy.SimpleRule{
{Name: "pipelines", Actions: []string{"view"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "members", Actions: []string{"view"}},
{Name: "devops", Actions: []string{"view"}},
}
break
}
return rules
}
// Get user roles in namespace
func (am *amOperator) GetUserRoles(namespace, username string) ([]*rbacv1.Role, error) {
clusterRoleLister := am.informers.Rbac().V1().ClusterRoles().Lister()
roleBindingLister := am.informers.Rbac().V1().RoleBindings().Lister()
roleLister := am.informers.Rbac().V1().Roles().Lister()
roleBindings, err := roleBindingLister.RoleBindings(namespace).List(labels.Everything())
if err != nil {
klog.Errorln(err)
return nil, err
}
roles := make([]*rbacv1.Role, 0)
for _, roleBinding := range roleBindings {
if ContainsUser(roleBinding.Subjects, username) {
if roleBinding.RoleRef.Kind == ClusterRoleKind {
clusterRole, err := clusterRoleLister.Get(roleBinding.RoleRef.Name)
if err != nil {
if apierrors.IsNotFound(err) {
klog.Warningf("cluster role %s not found but bind user %s in namespace %s", roleBinding.RoleRef.Name, username, namespace)
continue
} else {
klog.Errorln(err)
return nil, err
}
}
role := rbacv1.Role{}
role.TypeMeta = clusterRole.TypeMeta
role.ObjectMeta = clusterRole.ObjectMeta
role.Rules = clusterRole.Rules
role.Namespace = roleBinding.Namespace
roles = append(roles, &role)
} else {
role, err := roleLister.Roles(roleBinding.Namespace).Get(roleBinding.RoleRef.Name)
if err != nil {
if apierrors.IsNotFound(err) {
klog.Warningf("namespace %s role %s not found, but bind user %s", namespace, roleBinding.RoleRef.Name, username)
continue
} else {
klog.Errorln(err)
return nil, err
}
}
roles = append(roles, role)
}
}
}
return roles, nil
}
func (am *amOperator) GetUserClusterRoles(username string) (*rbacv1.ClusterRole, []*rbacv1.ClusterRole, error) {
clusterRoleLister := am.informers.Rbac().V1().ClusterRoles().Lister()
clusterRoleBindingLister := am.informers.Rbac().V1().ClusterRoleBindings().Lister()
clusterRoleBindings, err := clusterRoleBindingLister.List(labels.Everything())
if err != nil {
klog.Errorln(err)
return nil, nil, err
}
clusterRoles := make([]*rbacv1.ClusterRole, 0)
userFacingClusterRole := &rbacv1.ClusterRole{}
for _, clusterRoleBinding := range clusterRoleBindings {
if ContainsUser(clusterRoleBinding.Subjects, username) {
clusterRole, err := clusterRoleLister.Get(clusterRoleBinding.RoleRef.Name)
if err != nil {
if apierrors.IsNotFound(err) {
klog.Warningf("cluster role %s not found but bind user %s", clusterRoleBinding.RoleRef.Name, username)
continue
} else {
klog.Errorln(err)
return nil, nil, err
}
}
if clusterRoleBinding.Name == username {
userFacingClusterRole = clusterRole
}
clusterRoles = append(clusterRoles, clusterRole)
}
}
return userFacingClusterRole, clusterRoles, nil
}
func (am *amOperator) GetClusterRole(username string) (*rbacv1.ClusterRole, error) {
userFacingClusterRole, _, err := am.GetUserClusterRoles(username)
if err != nil {
return nil, err
}
return userFacingClusterRole, nil
}
func (am *amOperator) GetUserClusterRules(username string) ([]rbacv1.PolicyRule, error) {
_, clusterRoles, err := am.GetUserClusterRoles(username)
if err != nil {
return nil, err
}
rules := make([]rbacv1.PolicyRule, 0)
for _, clusterRole := range clusterRoles {
rules = append(rules, clusterRole.Rules...)
}
return rules, nil
}
func (am *amOperator) GetUserRules(namespace, username string) ([]rbacv1.PolicyRule, error) {
roles, err := am.GetUserRoles(namespace, username)
if err != nil {
return nil, err
}
rules := make([]rbacv1.PolicyRule, 0)
for _, role := range roles {
rules = append(rules, role.Rules...)
}
return rules, nil
}
func (am *amOperator) GetWorkspaceRoleBindings(workspace string) ([]*rbacv1.ClusterRoleBinding, error) {
clusterRoleBindings, err := am.informers.Rbac().V1().ClusterRoleBindings().Lister().List(labels.Everything())
if err != nil {
klog.Errorln("get cluster role bindings", err)
return nil, err
}
result := make([]*rbacv1.ClusterRoleBinding, 0)
for _, roleBinding := range clusterRoleBindings {
if k8sutil.IsControlledBy(roleBinding.OwnerReferences, "Workspace", workspace) {
result = append(result, roleBinding)
}
}
return result, nil
}
//func (am *amOperator) GetWorkspaceRole(workspace, role string) (*rbacv1.ClusterRole, error) {
// if !sliceutil.HasString(constants.WorkSpaceRoles, role) {
// return nil, apierrors.NewNotFound(schema.GroupResource{Resource: "workspace role"}, role)
// }
// role = fmt.Sprintf("workspace:%s:%s", workspace, strings.TrimPrefix(role, "workspace-"))
// return am.informers.Rbac().V1().ClusterRoles().Lister().Get(role)
//}
func (am *amOperator) GetWorkspaceRoleMap(username string) (map[string]string, error) {
clusterRoleBindings, err := am.informers.Rbac().V1().ClusterRoleBindings().Lister().List(labels.Everything())
if err != nil {
klog.Errorln("get cluster role bindings", err)
return nil, err
}
result := make(map[string]string, 0)
for _, roleBinding := range clusterRoleBindings {
if workspace := k8sutil.GetControlledWorkspace(roleBinding.OwnerReferences); workspace != "" &&
ContainsUser(roleBinding.Subjects, username) {
result[workspace] = roleBinding.RoleRef.Name
}
}
return result, nil
}
func (am *amOperator) GetUserWorkspaceRole(workspace, username string) (*rbacv1.ClusterRole, error) {
workspaceRoleMap, err := am.GetWorkspaceRoleMap(username)
if err != nil {
return nil, err
}
if workspaceRole := workspaceRoleMap[workspace]; workspaceRole != "" {
return am.informers.Rbac().V1().ClusterRoles().Lister().Get(workspaceRole)
}
return nil, apierrors.NewNotFound(schema.GroupResource{Resource: "workspace user"}, username)
}
func (am *amOperator) GetRoleBindings(namespace string, roleName string) ([]*rbacv1.RoleBinding, error) {
roleBindingLister := am.informers.Rbac().V1().RoleBindings().Lister()
roleBindings, err := roleBindingLister.RoleBindings(namespace).List(labels.Everything())
if err != nil {
klog.Errorln(err)
return nil, err
}
items := make([]*rbacv1.RoleBinding, 0)
for _, roleBinding := range roleBindings {
if roleName == "" {
items = append(items, roleBinding)
} else if roleBinding.RoleRef.Name == roleName {
items = append(items, roleBinding)
}
}
return items, nil
}
func (am *amOperator) GetClusterRoleBindings(clusterRoleName string) ([]*rbacv1.ClusterRoleBinding, error) {
clusterRoleBindingLister := am.informers.Rbac().V1().ClusterRoleBindings().Lister()
roleBindings, err := clusterRoleBindingLister.List(labels.Everything())
if err != nil {
klog.Errorln(err)
return nil, err
}
items := make([]*rbacv1.ClusterRoleBinding, 0)
for _, roleBinding := range roleBindings {
if roleBinding.RoleRef.Name == clusterRoleName {
items = append(items, roleBinding)
}
}
return items, nil
}
func (am *amOperator) ListRoles(namespace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
return am.resources.ListResources(namespace, v1alpha2.Roles, conditions, orderBy, reverse, limit, offset)
}
func (am *amOperator) ListRoleBindings(namespace string, role string) ([]*rbacv1.RoleBinding, error) {
rbs, err := am.informers.Rbac().V1().RoleBindings().Lister().RoleBindings(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*rbacv1.RoleBinding, 0)
for _, rb := range rbs {
if rb.RoleRef.Name == role {
result = append(result, rb.DeepCopy())
}
}
return result, nil
}
func (am *amOperator) ListWorkspaceRoles(workspace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
conditions.Match[v1alpha2.OwnerName] = workspace
conditions.Match[v1alpha2.OwnerKind] = "Workspace"
result, err := am.resources.ListResources("", v1alpha2.ClusterRoles, conditions, orderBy, reverse, limit, offset)
if err != nil {
return nil, err
}
for i, item := range result.Items {
if role, ok := item.(*rbacv1.ClusterRole); ok {
role = role.DeepCopy()
role.Name = role.Annotations[constants.DisplayNameAnnotationKey]
result.Items[i] = role
}
}
return result, nil
}
func (am *amOperator) ListClusterRoles(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
return am.resources.ListResources("", v1alpha2.ClusterRoles, conditions, orderBy, reverse, limit, offset)
}
func (am *amOperator) GetWorkspaceRoleSimpleRules(workspace, roleName string) []policy.SimpleRule {
workspaceRules := make([]policy.SimpleRule, 0)
switch roleName {
case constants.WorkspaceAdmin:
workspaceRules = []policy.SimpleRule{
{Name: "workspaces", Actions: []string{"edit", "delete", "view"}},
{Name: "members", Actions: []string{"edit", "delete", "create", "view"}},
{Name: "devops", Actions: []string{"edit", "delete", "create", "view"}},
{Name: "projects", Actions: []string{"edit", "delete", "create", "view"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "apps", Actions: []string{"view", "create", "manage"}},
{Name: "repos", Actions: []string{"view", "manage"}},
}
case constants.WorkspaceRegular:
workspaceRules = []policy.SimpleRule{
{Name: "members", Actions: []string{"view"}},
{Name: "devops", Actions: []string{"view", "create"}},
{Name: "projects", Actions: []string{"view", "create"}},
{Name: "apps", Actions: []string{"view", "create"}},
{Name: "repos", Actions: []string{"view"}},
}
case constants.WorkspaceViewer:
workspaceRules = []policy.SimpleRule{
{Name: "workspaces", Actions: []string{"view"}},
{Name: "members", Actions: []string{"view"}},
{Name: "devops", Actions: []string{"view"}},
{Name: "projects", Actions: []string{"view"}},
{Name: "roles", Actions: []string{"view"}},
{Name: "apps", Actions: []string{"view"}},
{Name: "repos", Actions: []string{"view"}},
}
case constants.WorkspacesManager:
workspaceRules = []policy.SimpleRule{
{Name: "workspaces", Actions: []string{"edit", "delete", "view"}},
{Name: "members", Actions: []string{"edit", "delete", "create", "view"}},
{Name: "roles", Actions: []string{"view"}},
}
}
return workspaceRules
}
// Convert cluster role to rules
func (am *amOperator) GetClusterRoleSimpleRules(clusterRoleName string) ([]policy.SimpleRule, error) {
clusterRoleLister := am.informers.Rbac().V1().ClusterRoles().Lister()
clusterRole, err := clusterRoleLister.Get(clusterRoleName)
if err != nil {
klog.Errorln(err)
return nil, err
}
return getClusterSimpleRule(clusterRole.Rules), nil
}
func (am *amOperator) GetUserClusterSimpleRules(username string) ([]policy.SimpleRule, error) {
clusterRules, err := am.GetUserClusterRules(username)
if err != nil {
return nil, err
}
return getClusterSimpleRule(clusterRules), nil
}
// Convert roles to rules
func (am *amOperator) GetRoleSimpleRules(namespace string, roleName string) ([]policy.SimpleRule, error) {
roleLister := am.informers.Rbac().V1().Roles().Lister()
role, err := roleLister.Roles(namespace).Get(roleName)
if err != nil {
klog.Errorln(err)
return nil, err
}
return ConvertToSimpleRule(role.Rules), nil
}
func getClusterSimpleRule(policyRules []rbacv1.PolicyRule) []policy.SimpleRule {
rules := make([]policy.SimpleRule, 0)
for i := 0; i < len(policy.ClusterRoleRuleMapping); i++ {
validActions := make([]string, 0)
for j := 0; j < (len(policy.ClusterRoleRuleMapping[i].Actions)); j++ {
if rulesMatchesAction(policyRules, policy.ClusterRoleRuleMapping[i].Actions[j]) {
validActions = append(validActions, policy.ClusterRoleRuleMapping[i].Actions[j].Name)
}
}
if len(validActions) > 0 {
rules = append(rules, policy.SimpleRule{Name: policy.ClusterRoleRuleMapping[i].Name, Actions: validActions})
}
}
return rules
}
func ConvertToSimpleRule(policyRules []rbacv1.PolicyRule) []policy.SimpleRule {
simpleRules := make([]policy.SimpleRule, 0)
for i := 0; i < len(policy.RoleRuleMapping); i++ {
rule := policy.SimpleRule{Name: policy.RoleRuleMapping[i].Name}
rule.Actions = make([]string, 0)
for j := 0; j < len(policy.RoleRuleMapping[i].Actions); j++ {
if rulesMatchesAction(policyRules, policy.RoleRuleMapping[i].Actions[j]) {
rule.Actions = append(rule.Actions, policy.RoleRuleMapping[i].Actions[j].Name)
}
}
if len(rule.Actions) > 0 {
simpleRules = append(simpleRules, rule)
}
}
return simpleRules
}
func (am *amOperator) CreateClusterRoleBinding(username string, clusterRoleName string) error {
clusterRoleLister := am.informers.Rbac().V1().ClusterRoles().Lister()
_, err := clusterRoleLister.Get(clusterRoleName)
if err != nil {
klog.Errorln(err)
return err
}
// TODO move to user controller
if clusterRoleName == constants.ClusterAdmin {
// create kubectl pod if cluster role is cluster-admin
//if err := kubectl.CreateKubectlDeploy(username); err != nil {
// klog.Error("create user terminal pod failed", username, err)
//}
} else {
// delete kubectl pod if cluster role is not cluster-admin, whether it exists or not
//if err := kubectl.DelKubectlDeploy(username); err != nil {
// klog.Error("delete user terminal pod failed", username, err)
//}
}
clusterRoleBinding := &rbacv1.ClusterRoleBinding{}
clusterRoleBinding.Name = username
clusterRoleBinding.RoleRef = rbacv1.RoleRef{Name: clusterRoleName, Kind: ClusterRoleKind}
clusterRoleBinding.Subjects = []rbacv1.Subject{{Kind: rbacv1.UserKind, Name: username}}
clusterRoleBindingLister := am.informers.Rbac().V1().ClusterRoleBindings().Lister()
found, err := clusterRoleBindingLister.Get(username)
if apierrors.IsNotFound(err) {
_, err = am.kubeClient.RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
if err != nil {
klog.Errorln("create cluster role binding", err)
return err
}
return nil
} else if err != nil {
return err
}
// cluster role changed
if found.RoleRef.Name != clusterRoleName {
deletePolicy := metav1.DeletePropagationBackground
gracePeriodSeconds := int64(0)
deleteOption := &metav1.DeleteOptions{PropagationPolicy: &deletePolicy, GracePeriodSeconds: &gracePeriodSeconds}
err = am.kubeClient.RbacV1().ClusterRoleBindings().Delete(found.Name, deleteOption)
if err != nil {
klog.Errorln(err)
return err
}
_, err = am.kubeClient.RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
if err != nil {
klog.Errorln(err)
return err
}
return nil
}
if !ContainsUser(found.Subjects, username) {
found.Subjects = clusterRoleBinding.Subjects
_, err = am.kubeClient.RbacV1().ClusterRoleBindings().Update(found)
if err != nil {
klog.Errorln("update cluster role binding", err)
return err
}
}
return nil
}

100
pkg/models/iam/am/am.go Normal file
View File

@@ -0,0 +1,100 @@
/*
*
* 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 (
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/clusterrole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/resource"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/role"
)
const (
ClusterRoleKind = "ClusterRole"
NamespaceAdminRoleBindName = "admin"
NamespaceViewerRoleBindName = "viewer"
)
type AccessManagementInterface interface {
GetPlatformRole(username string) (Role, error)
GetClusterRole(cluster, username string) (Role, error)
GetWorkspaceRole(workspace, username string) (Role, error)
GetNamespaceRole(namespace, username string) (Role, error)
GetDevOpsRole(project, username string) (Role, error)
}
type Role interface {
GetName() string
GetRego() string
}
type amOperator struct {
informers informers.SharedInformerFactory
resources resource.ResourceGetter
kubeClient kubernetes.Interface
}
func (am *amOperator) ListClusterRoleBindings(clusterRole string) ([]*rbacv1.ClusterRoleBinding, error) {
panic("implement me")
}
func (am *amOperator) GetRoles(namespace, username string) ([]*rbacv1.Role, error) {
panic("implement me")
}
func (am *amOperator) GetClusterPolicyRules(username string) ([]rbacv1.PolicyRule, error) {
panic("implement me")
}
func (am *amOperator) GetPolicyRules(namespace, username string) ([]rbacv1.PolicyRule, error) {
panic("implement me")
}
func (am *amOperator) GetWorkspaceRole(workspace, username string) (Role, error) {
panic("implement me")
}
func NewAMOperator(kubeClient kubernetes.Interface, informers informers.SharedInformerFactory) AccessManagementInterface {
resourceGetter := resource.ResourceGetter{}
resourceGetter.Add(v1alpha2.Role, role.NewRoleSearcher(informers))
resourceGetter.Add(v1alpha2.ClusterRoles, clusterrole.NewClusterRoleSearcher(informers))
return &amOperator{
informers: informers,
resources: resourceGetter,
kubeClient: kubeClient,
}
}
func (am *amOperator) GetPlatformRole(username string) (Role, error) {
panic("implement me")
}
func (am *amOperator) GetClusterRole(cluster, username string) (Role, error) {
panic("implement me")
}
func (am *amOperator) GetNamespaceRole(namespace, username string) (Role, error) {
panic("implement me")
}
func (am *amOperator) GetDevOpsRole(namespace, username string) (Role, error) {
panic("implement me")
}

View File

@@ -15,7 +15,7 @@
* limitations under the License.
* /
*/
package iam
package im
import (
"fmt"

View File

@@ -16,4 +16,4 @@
* /
*/
package iam
package im

File diff suppressed because it is too large Load Diff

View File

@@ -1,213 +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 iam
import (
rbacv1 "k8s.io/api/rbac/v1"
"kubesphere.io/kubesphere/pkg/api/iam"
"kubesphere.io/kubesphere/pkg/models/iam/policy"
"strings"
)
func RulesMatchesRequired(rules []rbacv1.PolicyRule, required rbacv1.PolicyRule) bool {
for _, rule := range rules {
if ruleMatchesRequired(rule, required) {
return true
}
}
return false
}
func rulesMatchesAction(rules []rbacv1.PolicyRule, action policy.Action) bool {
for _, required := range action.Rules {
if !RulesMatchesRequired(rules, required) {
return false
}
}
return true
}
func ruleMatchesRequired(rule rbacv1.PolicyRule, required rbacv1.PolicyRule) bool {
if len(required.NonResourceURLs) == 0 {
for _, apiGroup := range required.APIGroups {
for _, resource := range required.Resources {
resources := strings.Split(resource, "/")
resource = resources[0]
var subsource string
if len(resources) > 1 {
subsource = resources[1]
}
if len(required.ResourceNames) == 0 {
for _, verb := range required.Verbs {
if !ruleMatchesRequest(rule, apiGroup, "", resource, subsource, "", verb) {
return false
}
}
} else {
for _, resourceName := range required.ResourceNames {
for _, verb := range required.Verbs {
if !ruleMatchesRequest(rule, apiGroup, "", resource, subsource, resourceName, verb) {
return false
}
}
}
}
}
}
} else {
for _, apiGroup := range required.APIGroups {
for _, nonResourceURL := range required.NonResourceURLs {
for _, verb := range required.Verbs {
if !ruleMatchesRequest(rule, apiGroup, nonResourceURL, "", "", "", verb) {
return false
}
}
}
}
}
return true
}
func ruleMatchesResources(rule rbacv1.PolicyRule, apiGroup string, resource string, subresource string, resourceName string) bool {
if resource == "" {
return false
}
if !hasString(rule.APIGroups, apiGroup) && !hasString(rule.APIGroups, rbacv1.ResourceAll) {
return false
}
if len(rule.ResourceNames) > 0 && !hasString(rule.ResourceNames, resourceName) {
return false
}
combinedResource := resource
if subresource != "" {
combinedResource = combinedResource + "/" + subresource
}
for _, res := range rule.Resources {
// match "*"
if res == rbacv1.ResourceAll || res == combinedResource {
return true
}
// match "*/subresource"
if len(subresource) > 0 && strings.HasPrefix(res, "*/") && subresource == strings.TrimLeft(res, "*/") {
return true
}
// match "resource/*"
if strings.HasSuffix(res, "/*") && resource == strings.TrimRight(res, "/*") {
return true
}
}
return false
}
func ruleMatchesRequest(rule rbacv1.PolicyRule, apiGroup string, nonResourceURL string, resource string, subresource string, resourceName string, verb string) bool {
if !hasString(rule.Verbs, verb) && !hasString(rule.Verbs, rbacv1.VerbAll) {
return false
}
if nonResourceURL == "" {
return ruleMatchesResources(rule, apiGroup, resource, subresource, resourceName)
} else {
return ruleMatchesNonResource(rule, nonResourceURL)
}
}
func ruleMatchesNonResource(rule rbacv1.PolicyRule, nonResourceURL string) bool {
if nonResourceURL == "" {
return false
}
for _, spec := range rule.NonResourceURLs {
if pathMatches(nonResourceURL, spec) {
return true
}
}
return false
}
func pathMatches(path, spec string) bool {
// Allow wildcard match
if spec == "*" {
return true
}
// Allow exact match
if spec == path {
return true
}
// Allow a trailing * subpath match
if strings.HasSuffix(spec, "*") && strings.HasPrefix(path, strings.TrimRight(spec, "*")) {
return true
}
return false
}
func hasString(slice []string, value string) bool {
for _, s := range slice {
if s == value {
return true
}
}
return false
}
func ContainsUser(subjects interface{}, username string) bool {
switch subjects.(type) {
case []*rbacv1.Subject:
for _, subject := range subjects.([]*rbacv1.Subject) {
if subject.Kind == rbacv1.UserKind && subject.Name == username {
return true
}
}
case []rbacv1.Subject:
for _, subject := range subjects.([]rbacv1.Subject) {
if subject.Kind == rbacv1.UserKind && subject.Name == username {
return true
}
}
case []iam.User:
for _, u := range subjects.([]iam.User) {
if u.Username == username {
return true
}
}
case []*iam.User:
for _, u := range subjects.([]*iam.User) {
if u.Username == username {
return true
}
}
}
return false
}