code refactor (#1786)
* implement LDAP mock client Signed-off-by: hongming <talonwan@yunify.com> * update Signed-off-by: hongming <talonwan@yunify.com> * update Signed-off-by: hongming <talonwan@yunify.com> * resolve conflict Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
@@ -18,8 +18,6 @@
|
||||
package iam
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-ldap/ldap"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -38,9 +36,6 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -50,9 +45,21 @@ const (
|
||||
)
|
||||
|
||||
type AccessManagementInterface interface {
|
||||
GetDevopsRoleSimpleRules(role string) []SimpleRule
|
||||
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) ([]SimpleRule, error)
|
||||
GetRoleSimpleRules(namespace string, role string) ([]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) []SimpleRule
|
||||
GetWorkspaceRole(workspace, username string) (*rbacv1.ClusterRole, error)
|
||||
GetWorkspaceRoleMap(username string) (map[string]string, error)
|
||||
}
|
||||
|
||||
type amOperator struct {
|
||||
@@ -60,7 +67,31 @@ type amOperator struct {
|
||||
resources resource.ResourceGetter
|
||||
}
|
||||
|
||||
func newAMOperator(informers informers.SharedInformerFactory) AccessManagementInterface {
|
||||
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(informers informers.SharedInformerFactory) *amOperator {
|
||||
resourceGetter := resource.ResourceGetter{}
|
||||
resourceGetter.Add(v1alpha2.Role, role.NewRoleSearcher(informers))
|
||||
resourceGetter.Add(v1alpha2.ClusterRoles, clusterrole.NewClusterRoleSearcher(informers))
|
||||
@@ -198,7 +229,7 @@ func (am *amOperator) GetUserClusterRoles(username string) (*rbacv1.ClusterRole,
|
||||
return userFacingClusterRole, clusterRoles, nil
|
||||
}
|
||||
|
||||
func (am *amOperator) GetUserClusterRole(username string) (*rbacv1.ClusterRole, error) {
|
||||
func (am *amOperator) GetClusterRole(username string) (*rbacv1.ClusterRole, error) {
|
||||
userFacingClusterRole, _, err := am.GetUserClusterRoles(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -256,15 +287,15 @@ func (am *amOperator) GetWorkspaceRoleBindings(workspace string) ([]*rbacv1.Clus
|
||||
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) 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) GetUserWorkspaceRoleMap(username string) (map[string]string, error) {
|
||||
func (am *amOperator) GetWorkspaceRoleMap(username string) (map[string]string, error) {
|
||||
|
||||
clusterRoleBindings, err := am.informers.Rbac().V1().ClusterRoleBindings().Lister().List(labels.Everything())
|
||||
|
||||
@@ -286,7 +317,7 @@ func (am *amOperator) GetUserWorkspaceRoleMap(username string) (map[string]strin
|
||||
}
|
||||
|
||||
func (am *amOperator) GetUserWorkspaceRole(workspace, username string) (*rbacv1.ClusterRole, error) {
|
||||
workspaceRoleMap, err := am.GetUserWorkspaceRoleMap(username)
|
||||
workspaceRoleMap, err := am.GetWorkspaceRoleMap(username)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -341,55 +372,6 @@ func (am *amOperator) GetClusterRoleBindings(clusterRoleName string) ([]*rbacv1.
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (am *amOperator) ListClusterRoleUsers(clusterRoleName string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
|
||||
|
||||
roleBindings, err := am.GetClusterRoleBindings(clusterRoleName)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
users := make([]*User, 0)
|
||||
for _, roleBinding := range roleBindings {
|
||||
for _, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == rbacv1.UserKind && !k8sutil.ContainsUser(users, subject.Name) {
|
||||
user, err := GetUserInfo(subject.Name)
|
||||
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
users = append(users, user)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// order & reverse
|
||||
sort.Slice(users, func(i, j int) bool {
|
||||
if reverse {
|
||||
i, j = j, i
|
||||
}
|
||||
switch orderBy {
|
||||
default:
|
||||
fallthrough
|
||||
case v1alpha2.Name:
|
||||
return strings.Compare(users[i].Username, users[j].Username) <= 0
|
||||
}
|
||||
})
|
||||
|
||||
result := make([]interface{}, 0)
|
||||
|
||||
for i, d := range users {
|
||||
if i >= offset && (limit == -1 || len(result) < limit) {
|
||||
result = append(result, d)
|
||||
}
|
||||
}
|
||||
|
||||
return &models.PageableResponse{Items: result, TotalCount: len(users)}, 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)
|
||||
}
|
||||
@@ -431,92 +413,6 @@ func (am *amOperator) ListClusterRoles(conditions *params.Conditions, orderBy st
|
||||
return am.resources.ListResources("", v1alpha2.ClusterRoles, conditions, orderBy, reverse, limit, offset)
|
||||
}
|
||||
|
||||
func (am *amOperator) NamespaceUsers(namespaceName string) ([]*User, error) {
|
||||
namespace, err := am.informers.Core().V1().Namespaces().Lister().Get(namespaceName)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
roleBindings, err := am.GetRoleBindings(namespaceName, "")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users := make([]*User, 0)
|
||||
|
||||
for _, roleBinding := range roleBindings {
|
||||
// controlled by ks-controller-manager
|
||||
if roleBinding.Name == NamespaceViewerRoleBindName {
|
||||
continue
|
||||
}
|
||||
for _, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == rbacv1.UserKind && !k8sutil.ContainsUser(users, subject.Name) {
|
||||
|
||||
// show creator
|
||||
if roleBinding.Name == NamespaceAdminRoleBindName && subject.Name != namespace.Annotations[constants.CreatorAnnotationKey] {
|
||||
continue
|
||||
}
|
||||
|
||||
user, err := GetUserInfo(subject.Name)
|
||||
|
||||
if err != nil {
|
||||
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user.Role = roleBinding.RoleRef.Name
|
||||
user.RoleBindTime = &roleBinding.CreationTimestamp.Time
|
||||
user.RoleBinding = roleBinding.Name
|
||||
users = append(users, user)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (am *amOperator) GetUserWorkspaceSimpleRules(workspace, username string) ([]SimpleRule, error) {
|
||||
clusterRules, err := am.GetUserClusterRules(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// cluster-admin
|
||||
if RulesMatchesRequired(clusterRules, rbacv1.PolicyRule{
|
||||
Verbs: []string{"*"},
|
||||
APIGroups: []string{"*"},
|
||||
Resources: []string{"*"},
|
||||
}) {
|
||||
return am.GetWorkspaceRoleSimpleRules(workspace, constants.WorkspaceAdmin), nil
|
||||
}
|
||||
|
||||
workspaceRole, err := am.GetUserWorkspaceRole(workspace, username)
|
||||
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
|
||||
// workspaces-manager
|
||||
if RulesMatchesRequired(clusterRules, rbacv1.PolicyRule{
|
||||
Verbs: []string{"*"},
|
||||
APIGroups: []string{"*"},
|
||||
Resources: []string{"workspaces", "workspaces/*"},
|
||||
}) {
|
||||
return am.GetWorkspaceRoleSimpleRules(workspace, constants.WorkspacesManager), nil
|
||||
}
|
||||
|
||||
return []SimpleRule{}, nil
|
||||
}
|
||||
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return am.GetWorkspaceRoleSimpleRules(workspace, workspaceRole.Annotations[constants.DisplayNameAnnotationKey]), nil
|
||||
}
|
||||
|
||||
func (am *amOperator) GetWorkspaceRoleSimpleRules(workspace, roleName string) []SimpleRule {
|
||||
|
||||
workspaceRules := make([]SimpleRule, 0)
|
||||
@@ -583,20 +479,6 @@ func (am *amOperator) GetUserClusterSimpleRules(username string) ([]SimpleRule,
|
||||
return getClusterSimpleRule(clusterRules), nil
|
||||
}
|
||||
|
||||
func (am *amOperator) GetUserNamespaceSimpleRules(namespace, username string) ([]SimpleRule, error) {
|
||||
clusterRules, err := am.GetUserClusterRules(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rules, err := am.GetUserRules(namespace, username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rules = append(rules, clusterRules...)
|
||||
|
||||
return getSimpleRule(rules), nil
|
||||
}
|
||||
|
||||
// Convert roles to rules
|
||||
func (am *amOperator) GetRoleSimpleRules(namespace string, roleName string) ([]SimpleRule, error) {
|
||||
|
||||
@@ -608,7 +490,7 @@ func (am *amOperator) GetRoleSimpleRules(namespace string, roleName string) ([]S
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return getSimpleRule(role.Rules), nil
|
||||
return ConvertToSimpleRule(role.Rules), nil
|
||||
}
|
||||
|
||||
func getClusterSimpleRule(policyRules []rbacv1.PolicyRule) []SimpleRule {
|
||||
@@ -629,7 +511,7 @@ func getClusterSimpleRule(policyRules []rbacv1.PolicyRule) []SimpleRule {
|
||||
return rules
|
||||
}
|
||||
|
||||
func getSimpleRule(policyRules []rbacv1.PolicyRule) []SimpleRule {
|
||||
func ConvertToSimpleRule(policyRules []rbacv1.PolicyRule) []SimpleRule {
|
||||
simpleRules := make([]SimpleRule, 0)
|
||||
for i := 0; i < len(policy.RoleRuleMapping); i++ {
|
||||
rule := SimpleRule{Name: policy.RoleRuleMapping[i].Name}
|
||||
|
||||
1070
pkg/models/iam/im.go
1070
pkg/models/iam/im.go
File diff suppressed because it is too large
Load Diff
55
pkg/models/iam/im_test.go
Normal file
55
pkg/models/iam/im_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
*
|
||||
* 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 (
|
||||
"github.com/golang/mock/gomock"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIMOperator(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
ldappool, err := ldap.NewMockClient(&ldap.Options{
|
||||
Host: "192.168.0.7:30389",
|
||||
ManagerDN: "cn=admin,dc=kubesphere,dc=io",
|
||||
ManagerPassword: "admin",
|
||||
UserSearchBase: "ou=Users,dc=kubesphere,dc=io",
|
||||
GroupSearchBase: "ou=Groups,dc=kubesphere,dc=io",
|
||||
InitialCap: 8,
|
||||
MaxCap: 64,
|
||||
}, ctrl, func(client *ldap.MockClient) {
|
||||
client.EXPECT().Search(gomock.Any()).AnyTimes()
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer ldappool.Close()
|
||||
|
||||
im := NewIMOperator(ldappool, Config{})
|
||||
|
||||
err = im.Init()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,16 @@ const (
|
||||
KindTokenReview = "TokenReview"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
Lang string `json:"lang,omitempty"`
|
||||
Description string `json:"description"`
|
||||
CreateTime time.Time `json:"create_time"`
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
type Action struct {
|
||||
Name string `json:"name"`
|
||||
Rules []v1.PolicyRule `json:"rules"`
|
||||
@@ -47,15 +57,3 @@ type RoleList struct {
|
||||
ClusterRoles []*v1.ClusterRole `json:"clusterRole" description:"cluster role list"`
|
||||
Roles []*v1.Role `json:"roles" description:"role list"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
adminEmail string
|
||||
adminPassword string
|
||||
authRateLimit string
|
||||
maxAuthFailed int
|
||||
authTimeInterval time.Duration
|
||||
tokenIdleTimeout time.Duration
|
||||
userInitFile string
|
||||
enableMultiLogin bool
|
||||
generateKubeConfig bool
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@ func TestApplicationOperator_CreateApplication(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
op := openpitrix.NewMockClient(ctrl)
|
||||
objs := namespacesToRuntimeObjects(test.existNamespaces...)
|
||||
k8s := fake.NewSimpleClientset(objs...)
|
||||
|
||||
@@ -41,6 +41,7 @@ type NamespaceInterface interface {
|
||||
type namespaceSearcher struct {
|
||||
k8s kubernetes.Interface
|
||||
informers k8sinformers.SharedInformerFactory
|
||||
am iam.AccessManagementInterface
|
||||
}
|
||||
|
||||
func (s *namespaceSearcher) CreateNamespace(workspace string, namespace *v1.Namespace, username string) (*v1.Namespace, error) {
|
||||
@@ -56,8 +57,8 @@ func (s *namespaceSearcher) CreateNamespace(workspace string, namespace *v1.Name
|
||||
return s.k8s.CoreV1().Namespaces().Create(namespace)
|
||||
}
|
||||
|
||||
func newNamespaceOperator(k8s kubernetes.Interface, informers k8sinformers.SharedInformerFactory) NamespaceInterface {
|
||||
return &namespaceSearcher{k8s: k8s, informers: informers}
|
||||
func newNamespaceOperator(k8s kubernetes.Interface, informers k8sinformers.SharedInformerFactory, am iam.AccessManagementInterface) NamespaceInterface {
|
||||
return &namespaceSearcher{k8s: k8s, informers: informers, am: am}
|
||||
}
|
||||
|
||||
func (s *namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool {
|
||||
@@ -111,7 +112,7 @@ func (s *namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
|
||||
|
||||
func (s *namespaceSearcher) GetNamespaces(username string) ([]*v1.Namespace, error) {
|
||||
|
||||
roles, err := iam.GetUserRoles("", username)
|
||||
roles, err := s.am.GetRoles("", username)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -143,7 +144,7 @@ func containsNamespace(namespaces []*v1.Namespace, namespace *v1.Namespace) bool
|
||||
|
||||
func (s *namespaceSearcher) Search(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1.Namespace, error) {
|
||||
|
||||
rules, err := iam.GetUserClusterRules(username)
|
||||
rules, err := s.am.GetClusterPolicyRules(username)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -19,12 +19,16 @@ package tenant
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
k8sinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
"strconv"
|
||||
@@ -36,14 +40,35 @@ type Interface interface {
|
||||
DescribeWorkspace(username, workspace string) (*v1alpha1.Workspace, error)
|
||||
ListWorkspaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
|
||||
ListNamespaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
|
||||
GetWorkspace(workspace string) (*v1alpha1.Workspace, error)
|
||||
DevOpsProjectOperator
|
||||
ListDevopsProjects(username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
|
||||
GetWorkspaceSimpleRules(workspace, username string) ([]iam.SimpleRule, error)
|
||||
GetNamespaceSimpleRules(namespace, username string) ([]iam.SimpleRule, error)
|
||||
CountDevOpsProjects(username string) (uint32, error)
|
||||
DeleteDevOpsProject(username, projectId string) error
|
||||
GetUserDevopsSimpleRules(username string, devops string) (interface{}, error)
|
||||
}
|
||||
|
||||
type tenantOperator struct {
|
||||
workspaces WorkspaceInterface
|
||||
namespaces NamespaceInterface
|
||||
DevOpsProjectOperator
|
||||
am iam.AccessManagementInterface
|
||||
devops DevOpsProjectOperator
|
||||
}
|
||||
|
||||
func (t *tenantOperator) CountDevOpsProjects(username string) (uint32, error) {
|
||||
return t.devops.GetDevOpsProjectsCount(username)
|
||||
}
|
||||
|
||||
func (t *tenantOperator) DeleteDevOpsProject(username, projectId string) error {
|
||||
return t.devops.DeleteDevOpsProject(projectId, username)
|
||||
}
|
||||
|
||||
func (t *tenantOperator) GetUserDevopsSimpleRules(username string, projectId string) (interface{}, error) {
|
||||
return t.devops.GetUserDevOpsSimpleRules(username, projectId)
|
||||
}
|
||||
|
||||
func (t *tenantOperator) ListDevopsProjects(username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
|
||||
return t.devops.ListDevOpsProjects(conditions.Match["workspace"], username, conditions, orderBy, reverse, limit, offset)
|
||||
}
|
||||
|
||||
func (t *tenantOperator) DeleteNamespace(workspace, namespace string) error {
|
||||
@@ -51,9 +76,11 @@ func (t *tenantOperator) DeleteNamespace(workspace, namespace string) error {
|
||||
}
|
||||
|
||||
func New(client kubernetes.Interface, informers k8sinformers.SharedInformerFactory, ksinformers ksinformers.SharedInformerFactory, db *mysql.Database) Interface {
|
||||
amOperator := iam.NewAMOperator(informers)
|
||||
return &tenantOperator{
|
||||
workspaces: newWorkspaceOperator(client, informers, ksinformers, db),
|
||||
namespaces: newNamespaceOperator(client, informers),
|
||||
workspaces: newWorkspaceOperator(client, informers, ksinformers, amOperator, db),
|
||||
namespaces: newNamespaceOperator(client, informers, amOperator),
|
||||
am: amOperator,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,17 +122,69 @@ func (t *tenantOperator) ListWorkspaces(username string, conditions *params.Cond
|
||||
return &models.PageableResponse{Items: result, TotalCount: len(workspaces)}, nil
|
||||
}
|
||||
|
||||
func (t *tenantOperator) GetWorkspaceSimpleRules(workspace, username string) ([]iam.SimpleRule, error) {
|
||||
clusterRules, err := t.am.GetClusterPolicyRules(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// cluster-admin
|
||||
if iam.RulesMatchesRequired(clusterRules, rbacv1.PolicyRule{
|
||||
Verbs: []string{"*"},
|
||||
APIGroups: []string{"*"},
|
||||
Resources: []string{"*"},
|
||||
}) {
|
||||
return t.am.GetWorkspaceRoleSimpleRules(workspace, constants.WorkspaceAdmin), nil
|
||||
}
|
||||
|
||||
workspaceRole, err := t.am.GetWorkspaceRole(workspace, username)
|
||||
|
||||
// workspaces-manager
|
||||
if iam.RulesMatchesRequired(clusterRules, rbacv1.PolicyRule{
|
||||
Verbs: []string{"*"},
|
||||
APIGroups: []string{"*"},
|
||||
Resources: []string{"workspaces", "workspaces/*"},
|
||||
}) {
|
||||
return t.am.GetWorkspaceRoleSimpleRules(workspace, constants.WorkspacesManager), nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return []iam.SimpleRule{}, nil
|
||||
}
|
||||
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return t.am.GetWorkspaceRoleSimpleRules(workspace, workspaceRole.Annotations[constants.DisplayNameAnnotationKey]), nil
|
||||
}
|
||||
|
||||
func (t *tenantOperator) GetNamespaceSimpleRules(namespace, username string) ([]iam.SimpleRule, error) {
|
||||
clusterRules, err := t.am.GetClusterPolicyRules(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rules, err := t.am.GetPolicyRules(namespace, username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rules = append(rules, clusterRules...)
|
||||
|
||||
return iam.ConvertToSimpleRule(rules), nil
|
||||
}
|
||||
|
||||
func (t *tenantOperator) appendAnnotations(username string, workspace *v1alpha1.Workspace) *v1alpha1.Workspace {
|
||||
workspace = workspace.DeepCopy()
|
||||
if workspace.Annotations == nil {
|
||||
workspace.Annotations = make(map[string]string)
|
||||
}
|
||||
ns, err := t.ListNamespaces(username, ¶ms.Conditions{Match: map[string]string{constants.WorkspaceLabelKey: workspace.Name}}, "", false, 1, 0)
|
||||
if err == nil {
|
||||
|
||||
if ns, err := t.ListNamespaces(username, ¶ms.Conditions{Match: map[string]string{constants.WorkspaceLabelKey: workspace.Name}}, "", false, 1, 0); err == nil {
|
||||
workspace.Annotations["kubesphere.io/namespace-count"] = strconv.Itoa(ns.TotalCount)
|
||||
}
|
||||
devops, err := t.ListDevOpsProjects(workspace.Name, username, ¶ms.Conditions{}, "", false, 1, 0)
|
||||
if err == nil {
|
||||
|
||||
if devops, err := t.ListDevopsProjects(username, ¶ms.Conditions{Match: map[string]string{"workspace": workspace.Name}}, "", false, 1, 0); err == nil {
|
||||
workspace.Annotations["kubesphere.io/devops-count"] = strconv.Itoa(devops.TotalCount)
|
||||
}
|
||||
|
||||
@@ -135,7 +214,3 @@ func (t *tenantOperator) ListNamespaces(username string, conditions *params.Cond
|
||||
|
||||
return &models.PageableResponse{Items: result, TotalCount: len(namespaces)}, nil
|
||||
}
|
||||
|
||||
func (t *tenantOperator) GetWorkspace(workspace string) (*v1alpha1.Workspace, error) {
|
||||
return t.workspaces.GetWorkspace(workspace)
|
||||
}
|
||||
|
||||
@@ -46,13 +46,18 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type InWorkspaceUser struct {
|
||||
*iam.User
|
||||
WorkspaceRole string `json:"workspaceRole"`
|
||||
}
|
||||
|
||||
type WorkspaceInterface interface {
|
||||
GetWorkspace(workspace string) (*v1alpha1.Workspace, error)
|
||||
SearchWorkspace(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1alpha1.Workspace, error)
|
||||
ListNamespaces(workspace string) ([]*core.Namespace, error)
|
||||
DeleteNamespace(workspace, namespace string) error
|
||||
RemoveUser(user, workspace string) error
|
||||
AddUser(workspace string, user *iam.User) error
|
||||
AddUser(workspace string, user *InWorkspaceUser) error
|
||||
CountDevopsProjectsInWorkspace(workspace string) (int, error)
|
||||
CountUsersInWorkspace(workspace string) (int, error)
|
||||
CountOrgRoles() (int, error)
|
||||
@@ -64,17 +69,19 @@ type workspaceOperator struct {
|
||||
client kubernetes.Interface
|
||||
informers informers.SharedInformerFactory
|
||||
ksInformers externalversions.SharedInformerFactory
|
||||
am iam.AccessManagementInterface
|
||||
|
||||
// TODO: use db interface instead of mysql client
|
||||
// we can refactor this after rewrite devops using crd
|
||||
db *mysql.Database
|
||||
}
|
||||
|
||||
func newWorkspaceOperator(client kubernetes.Interface, informers informers.SharedInformerFactory, ksinformers externalversions.SharedInformerFactory, db *mysql.Database) WorkspaceInterface {
|
||||
func newWorkspaceOperator(client kubernetes.Interface, informers informers.SharedInformerFactory, ksinformers externalversions.SharedInformerFactory, am iam.AccessManagementInterface, db *mysql.Database) WorkspaceInterface {
|
||||
return &workspaceOperator{
|
||||
client: client,
|
||||
informers: informers,
|
||||
ksInformers: ksinformers,
|
||||
am: am,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
@@ -104,7 +111,7 @@ func (w *workspaceOperator) DeleteNamespace(workspace string, namespace string)
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) RemoveUser(workspace string, username string) error {
|
||||
workspaceRole, err := iam.GetUserWorkspaceRole(workspace, username)
|
||||
workspaceRole, err := w.am.GetWorkspaceRole(workspace, username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -117,9 +124,9 @@ func (w *workspaceOperator) RemoveUser(workspace string, username string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) AddUser(workspaceName string, user *iam.User) error {
|
||||
func (w *workspaceOperator) AddUser(workspaceName string, user *InWorkspaceUser) error {
|
||||
|
||||
workspaceRole, err := iam.GetUserWorkspaceRole(workspaceName, user.Username)
|
||||
workspaceRole, err := w.am.GetWorkspaceRole(workspaceName, user.Username)
|
||||
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
klog.Errorf("get workspace role failed: %+v", err)
|
||||
@@ -215,7 +222,7 @@ func (w *workspaceOperator) CountDevopsProjectsInWorkspace(workspaceName string)
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) CountUsersInWorkspace(workspace string) (int, error) {
|
||||
count, err := iam.WorkspaceUsersTotalCount(workspace)
|
||||
count, err := w.CountUsersInWorkspace(workspace)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -285,7 +292,7 @@ func (*workspaceOperator) compare(a, b *v1alpha1.Workspace, orderBy string) bool
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) SearchWorkspace(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1alpha1.Workspace, error) {
|
||||
rules, err := iam.GetUserClusterRules(username)
|
||||
rules, err := w.am.GetClusterPolicyRules(username)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -299,7 +306,7 @@ func (w *workspaceOperator) SearchWorkspace(username string, conditions *params.
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
workspaceRoles, err := iam.GetUserWorkspaceRoleMap(username)
|
||||
workspaceRoles, err := w.am.GetWorkspaceRoleMap(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user