fix: devop IAM bugs

Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-07-27 13:06:13 +08:00
parent afcd0efea2
commit bda48c240f
15 changed files with 307 additions and 85 deletions

View File

@@ -70,8 +70,9 @@ type AccessManagementInterface interface {
RemoveUserFromNamespace(username string, namespace string) error
CreateClusterRoleBinding(username string, role string) error
RemoveUserFromCluster(username string) error
GetControlledNamespace(devops string) (string, error)
GetControlledWorkspace(namespace string) (string, error)
GetDevOpsRelatedNamespace(devops string) (string, error)
GetNamespaceControlledWorkspace(namespace string) (string, error)
GetDevOpsControlledWorkspace(devops string) (string, error)
PatchNamespaceRole(namespace string, role *rbacv1.Role) (*rbacv1.Role, error)
PatchClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error)
}
@@ -279,23 +280,19 @@ func (am *amOperator) ListGlobalRoleBindings(username string) ([]*iamv1alpha2.Gl
}
func (am *amOperator) ListRoleBindings(username, namespace string) ([]*rbacv1.RoleBinding, error) {
roleBindings, err := am.resourceGetter.List(iamv1alpha2.ResourcesPluralRoleBinding, namespace, query.New())
if err != nil {
klog.Error(err)
return nil, err
}
result := make([]*rbacv1.RoleBinding, 0)
for _, obj := range roleBindings.Items {
roleBinding := obj.(*rbacv1.RoleBinding)
if contains(roleBinding.Subjects, username) {
result = append(result, roleBinding)
}
}
return result, nil
}
@@ -964,7 +961,7 @@ func (am *amOperator) GetClusterRole(name string) (*rbacv1.ClusterRole, error) {
}
return obj.(*rbacv1.ClusterRole), nil
}
func (am *amOperator) GetControlledNamespace(devops string) (string, error) {
func (am *amOperator) GetDevOpsRelatedNamespace(devops string) (string, error) {
obj, err := am.resourceGetter.Get(devopsv1alpha3.ResourcePluralDevOpsProject, "", devops)
if err != nil {
klog.Error(err)
@@ -975,7 +972,17 @@ func (am *amOperator) GetControlledNamespace(devops string) (string, error) {
return devopsProject.Status.AdminNamespace, nil
}
func (am *amOperator) GetControlledWorkspace(namespace string) (string, error) {
func (am *amOperator) GetDevOpsControlledWorkspace(devops string) (string, error) {
obj, err := am.resourceGetter.Get(devopsv1alpha3.ResourcePluralDevOpsProject, "", devops)
if err != nil {
klog.Error(err)
return "", err
}
devopsProject := obj.(*devopsv1alpha3.DevOpsProject)
return devopsProject.Labels[tenantv1alpha1.WorkspaceLabel], nil
}
func (am *amOperator) GetNamespaceControlledWorkspace(namespace string) (string, error) {
obj, err := am.resourceGetter.Get("namespaces", "", namespace)
if err != nil {
if errors.IsNotFound(err) {

View File

@@ -17,26 +17,109 @@ limitations under the License.
package tenant
import (
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/server/params"
dsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
"fmt"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
devopsv1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/apiserver/request"
"kubesphere.io/kubesphere/pkg/constants"
resources "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
)
type DevOpsProjectLister interface {
ListDevOpsProjects(workspace string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
}
type devopsProjectLister struct {
dsProject dsClient.ProjectOperator
}
func newProjectLister(client dsClient.ProjectOperator) DevOpsProjectLister {
return &devopsProjectLister{
dsProject: client,
func (t *tenantOperator) ListDevOpsProjects(user user.Info, workspace string, queryParam *query.Query) (*api.ListResult, error) {
scope := request.ClusterScope
if workspace != "" {
scope = request.WorkspaceScope
}
}
func (o *devopsProjectLister) ListDevOpsProjects(workspace string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
//TODO: @runzexia use informer to impl it
return nil, nil
listDevOps := authorizer.AttributesRecord{
User: user,
Verb: "list",
Workspace: workspace,
Resource: "devops",
ResourceRequest: true,
ResourceScope: scope,
}
decision, _, err := t.authorizer.Authorize(listDevOps)
if err != nil {
klog.Error(err)
return nil, err
}
// allowed list devops in the specified scope
if decision == authorizer.DecisionAllow {
// filter by workspace
if workspace != "" {
queryParam.Filters[query.FieldLabel] = query.Value(fmt.Sprintf("%s=%s", tenantv1alpha1.WorkspaceLabel, workspace))
}
result, err := t.resourceGetter.List(devopsv1alpha3.ResourcePluralDevOpsProject, "", queryParam)
if err != nil {
klog.Error(err)
return nil, err
}
return result, nil
}
roleBindings, err := t.am.ListRoleBindings(user.GetName(), "")
if err != nil {
klog.Error(err)
return nil, err
}
devopsProjects := make([]runtime.Object, 0)
for _, roleBinding := range roleBindings {
obj, err := t.resourceGetter.Get("namespaces", "", roleBinding.Namespace)
if err != nil {
klog.Error(err)
return nil, err
}
namespace := obj.(*corev1.Namespace)
controlledDevOpsProject := namespace.Labels[constants.DevOpsProjectLabelKey]
// skip if not controlled by devops project
if controlledDevOpsProject == "" {
continue
}
devopsProject, err := t.resourceGetter.Get(devopsv1alpha3.ResourcePluralDevOpsProject, "", controlledDevOpsProject)
if err != nil {
if errors.IsNotFound(err) {
klog.Warning("orphan devops project found ", devopsProject)
continue
}
klog.Error(err)
return nil, err
}
// skip if not controlled by the specified workspace
if workspace != "" &&
devopsProject.(*devopsv1alpha3.DevOpsProject).Labels[tenantv1alpha1.WorkspaceLabel] != workspace {
continue
}
if !contains(devopsProjects, devopsProject) {
devopsProjects = append(devopsProjects, namespace)
}
}
result := resources.DefaultList(devopsProjects, queryParam, func(left runtime.Object, right runtime.Object, field query.Field) bool {
return resources.DefaultObjectMetaCompare(left.(*devopsv1alpha3.DevOpsProject).ObjectMeta, right.(*devopsv1alpha3.DevOpsProject).ObjectMeta, field)
}, func(object runtime.Object, filter query.Filter) bool {
devopsProject := object.(*devopsv1alpha3.DevOpsProject).ObjectMeta
if workspace != "" {
if workspaceLabel, ok := devopsProject.Labels[tenantv1alpha1.WorkspaceLabel]; !ok || workspaceLabel != workspace {
return false
}
}
return resources.DefaultObjectMetaFilter(devopsProject, filter)
})
return result, nil
}

View File

@@ -60,6 +60,7 @@ import (
type Interface interface {
ListWorkspaces(user user.Info, query *query.Query) (*api.ListResult, error)
ListNamespaces(user user.Info, workspace string, query *query.Query) (*api.ListResult, error)
ListDevOpsProjects(user user.Info, workspace string, query *query.Query) (*api.ListResult, error)
ListFederatedNamespaces(info user.Info, workspace string, param *query.Query) (*api.ListResult, error)
CreateNamespace(workspace string, namespace *corev1.Namespace) (*corev1.Namespace, error)
CreateWorkspace(workspace *tenantv1alpha2.WorkspaceTemplate) (*tenantv1alpha2.WorkspaceTemplate, error)