add rolebinding api

Signed-off-by: Roland.Ma <rolandma@yunify.com>
This commit is contained in:
Roland.Ma
2020-11-23 02:59:48 +00:00
parent 343b2e60f4
commit 079b43e301
4 changed files with 379 additions and 22 deletions

View File

@@ -77,6 +77,13 @@ type AccessManagementInterface interface {
GetDevOpsControlledWorkspace(devops string) (string, error)
PatchNamespaceRole(namespace string, role *rbacv1.Role) (*rbacv1.Role, error)
PatchClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error)
ListGroupRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error)
ListGroupDevOpsRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error)
CreateRoleBindings(namespace string, roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error)
DeleteRoleBindings(namespace, name string) error
ListGroupWorkspaceRoleBindings(group string, workspace string) ([]*iamv1alpha2.WorkspaceRoleBinding, error)
CreateWorkspaceRoleBindings(workspace string, roleBinding *iamv1alpha2.WorkspaceRoleBinding) (*iamv1alpha2.WorkspaceRoleBinding, error)
DeleteWorkspaceRoleBindings(workspaceName, name string) error
}
type amOperator struct {
@@ -998,3 +1005,155 @@ func (am *amOperator) GetNamespaceControlledWorkspace(namespace string) (string,
ns := obj.(*corev1.Namespace)
return ns.Labels[tenantv1alpha1.WorkspaceLabel], nil
}
func (am *amOperator) ListGroupWorkspaceRoleBindings(workspace, group string) ([]*iamv1alpha2.WorkspaceRoleBinding, error) {
q := workspaceQuery(workspace)
roleBindings, err := am.resourceGetter.List(iamv1alpha2.ResourcesPluralWorkspaceRoleBinding, "", q)
if err != nil {
return nil, err
}
result := make([]*iamv1alpha2.WorkspaceRoleBinding, 0)
for _, obj := range roleBindings.Items {
roleBinding := obj.(*iamv1alpha2.WorkspaceRoleBinding)
inSpecifiedWorkspace := workspace == "" || roleBinding.Labels[tenantv1alpha1.WorkspaceLabel] == workspace
if containsgroup(roleBinding.Subjects, group) && inSpecifiedWorkspace {
result = append(result, roleBinding)
}
}
return result, nil
}
func (am *amOperator) CreateWorkspaceRoleBindings(workspace string, roleBinding *iamv1alpha2.WorkspaceRoleBinding) (*iamv1alpha2.WorkspaceRoleBinding, error) {
_, err := am.GetWorkspaceRole(workspace, roleBinding.RoleRef.Name)
if err != nil {
klog.Error(err)
return nil, err
}
if len(roleBinding.Subjects) == 0 {
err := errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesPluralUser), "")
return nil, err
}
roleBinding.GenerateName = fmt.Sprintf("%s-%s-", roleBinding.Subjects[0].Name, roleBinding.RoleRef.Name)
if roleBinding.Labels == nil {
roleBinding.Labels = map[string]string{}
}
if roleBinding.Subjects[0].Kind == rbacv1.GroupKind {
roleBinding.Labels[iamv1alpha2.GroupReferenceLabel] = roleBinding.RoleRef.Name
} else if roleBinding.Subjects[0].Kind == rbacv1.UserKind {
roleBinding.Labels[iamv1alpha2.UserReferenceLabel] = roleBinding.RoleRef.Name
}
roleBinding.Labels[tenantv1alpha1.WorkspaceLabel] = workspace
return am.ksclient.IamV1alpha2().WorkspaceRoleBindings().Create(roleBinding)
}
func (am *amOperator) DeleteWorkspaceRoleBindings(workspaceName, name string) error {
return am.ksclient.IamV1alpha2().WorkspaceRoleBindings().Delete(name, metav1.NewDeleteOptions(0))
}
func (am *amOperator) ListGroupRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error) {
q := workspaceQuery(workspace)
namespaces, err := am.resourceGetter.List("namespaces", "", q)
if err != nil {
return nil, err
}
result := make([]*rbacv1.RoleBinding, 0)
for _, ns := range namespaces.Items {
namespace := ns.(*corev1.Namespace)
roleBindings, err := am.resourceGetter.List(iamv1alpha2.ResourcesPluralRoleBinding, namespace.Name, query.New())
if err != nil {
klog.Error(err)
return nil, err
}
for _, obj := range roleBindings.Items {
roleBinding := obj.(*rbacv1.RoleBinding)
if containsgroup(roleBinding.Subjects, group) {
result = append(result, roleBinding)
}
}
}
return result, nil
}
func (am *amOperator) ListGroupDevOpsRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error) {
q := workspaceQuery(workspace)
namespaces, err := am.resourceGetter.List(devopsv1alpha3.ResourcePluralDevOpsProject, "", q)
if err != nil {
return nil, err
}
result := make([]*rbacv1.RoleBinding, 0)
for _, ns := range namespaces.Items {
namespace := ns.(*devopsv1alpha3.DevOpsProject)
roleBindings, err := am.resourceGetter.List(iamv1alpha2.ResourcesPluralRoleBinding, namespace.Name, query.New())
if err != nil {
klog.Error(err)
return nil, err
}
for _, obj := range roleBindings.Items {
roleBinding := obj.(*rbacv1.RoleBinding)
if containsgroup(roleBinding.Subjects, group) {
result = append(result, roleBinding)
}
}
}
return result, nil
}
func (am *amOperator) CreateRoleBindings(namespace string, roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error) {
_, err := am.GetNamespaceRole(namespace, roleBinding.RoleRef.Name)
if err != nil {
klog.Error(err)
return nil, err
}
if len(roleBinding.Subjects) == 0 {
err := errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesPluralUser), "")
return nil, err
}
roleBinding.GenerateName = fmt.Sprintf("%s-%s-", roleBinding.Subjects[0].Name, roleBinding.RoleRef.Name)
if roleBinding.Labels == nil {
roleBinding.Labels = map[string]string{}
}
if roleBinding.Subjects[0].Kind == rbacv1.GroupKind {
roleBinding.Labels[iamv1alpha2.GroupReferenceLabel] = roleBinding.Subjects[0].Name
} else if roleBinding.Subjects[0].Kind == rbacv1.UserKind {
roleBinding.Labels[iamv1alpha2.UserReferenceLabel] = roleBinding.Subjects[0].Name
}
return am.k8sclient.RbacV1().RoleBindings(namespace).Create(roleBinding)
}
func (am *amOperator) DeleteRoleBindings(namespace, name string) error {
return am.k8sclient.RbacV1().RoleBindings(namespace).Delete(name, metav1.NewDeleteOptions(0))
}
func containsgroup(subjects []rbacv1.Subject, group string) bool {
for _, subject := range subjects {
if subject.Kind == rbacv1.GroupKind && subject.Name == group {
return true
}
}
return false
}
func workspaceQuery(workspace string) *query.Query {
q := query.New()
q.Filters[query.FieldLabel] = query.Value(fmt.Sprintf("%s=%s", tenantv1alpha1.WorkspaceLabel, workspace))
return q
}

View File

@@ -24,6 +24,7 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
@@ -43,7 +44,7 @@ type GroupOperator interface {
UpdateGroup(workspace string, group *iamv1alpha2.Group) (*iamv1alpha2.Group, error)
PatchGroup(workspace string, group *iamv1alpha2.Group) (*iamv1alpha2.Group, error)
DeleteGroupBinding(workspace, name string) error
CreateGroupBinding(workspace, groupName, userName string) error
CreateGroupBinding(workspace, groupName, userName string) (*iamv1alpha2.GroupBinding, error)
ListGroupBindings(workspace, group string, queryParam *query.Query) (*api.ListResult, error)
}
@@ -77,8 +78,43 @@ func (t *groupOperator) ListGroups(workspace string, queryParam *query.Query) (*
}
// CreateGroup adds a workspace label to group which indicates group is under the workspace
func (t *groupOperator) CreateGroup(workspace string, namespace *iamv1alpha2.Group) (*iamv1alpha2.Group, error) {
return t.ksclient.IamV1alpha2().Groups().Create(labelGroupWithWorkspaceName(namespace, workspace))
func (t *groupOperator) CreateGroup(workspace string, group *iamv1alpha2.Group) (*iamv1alpha2.Group, error) {
if group.GenerateName == "" {
err := errors.NewInvalid(iamv1alpha2.SchemeGroupVersion.WithKind(iamv1alpha2.ResourcePluralGroup).GroupKind(),
"", []*field.Error{field.Required(field.NewPath("metadata.generateName"), "generateName is required")})
klog.Error(err)
return nil, err
}
// generateName is used as displayName
// ensure generateName is unique in workspace scope
if unique, err := t.isGenerateNameUnique(workspace, group.GenerateName); err != nil {
return nil, err
} else if !unique {
err = errors.NewConflict(iamv1alpha2.Resource(iamv1alpha2.ResourcePluralGroup),
group.GenerateName, fmt.Errorf("a group named %s already exists in the workspace", group.GenerateName))
klog.Error(err)
return nil, err
}
return t.ksclient.IamV1alpha2().Groups().Create(labelGroupWithWorkspaceName(group, workspace))
}
func (t *groupOperator) isGenerateNameUnique(workspace, generateName string) (bool, error) {
result, err := t.ListGroups(workspace, query.New())
if err != nil {
klog.Error(err)
return false, err
}
for _, obj := range result.Items {
g := obj.(*iamv1alpha2.Group)
if g.GenerateName == generateName {
return false, err
}
}
return true, nil
}
func (t *groupOperator) DescribeGroup(workspace, group string) (*iamv1alpha2.Group, error) {
@@ -142,11 +178,11 @@ func (t *groupOperator) DeleteGroupBinding(workspace, name string) error {
return t.ksclient.IamV1alpha2().GroupBindings().Delete(name, metav1.NewDeleteOptions(0))
}
func (t *groupOperator) CreateGroupBinding(workspace, groupName, userName string) error {
func (t *groupOperator) CreateGroupBinding(workspace, groupName, userName string) (*iamv1alpha2.GroupBinding, error) {
groupBinding := iamv1alpha2.GroupBinding{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", groupName, userName),
GenerateName: fmt.Sprintf("%s-%s-", groupName, userName),
Labels: map[string]string{
iamv1alpha2.UserReferenceLabel: userName,
iamv1alpha2.GroupReferenceLabel: groupName,
@@ -161,11 +197,7 @@ func (t *groupOperator) CreateGroupBinding(workspace, groupName, userName string
},
}
if _, err := t.ksclient.IamV1alpha2().GroupBindings().Create(&groupBinding); err != nil {
return err
}
return nil
return t.ksclient.IamV1alpha2().GroupBindings().Create(&groupBinding)
}
func (t *groupOperator) ListGroupBindings(workspace, group string, queryParam *query.Query) (*api.ListResult, error) {