@@ -18,61 +18,118 @@
|
||||
package am
|
||||
|
||||
import (
|
||||
"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"
|
||||
"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 {
|
||||
GetPlatformRole(username string) (Role, error)
|
||||
GetClusterRole(cluster, username string) (Role, error)
|
||||
GetWorkspaceRole(workspace, username string) (Role, error)
|
||||
GetNamespaceRole(cluster, namespace, username string) (Role, error)
|
||||
}
|
||||
|
||||
type Role interface {
|
||||
GetName() string
|
||||
GetRego() string
|
||||
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
|
||||
resources resource.ResourceGetter
|
||||
kubeClient kubernetes.Interface
|
||||
informers informers.SharedInformerFactory
|
||||
ksClient kubesphere.Interface
|
||||
}
|
||||
|
||||
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))
|
||||
func NewAMOperator(ksClient kubesphere.Interface, informers informers.SharedInformerFactory) AccessManagementInterface {
|
||||
return &amOperator{
|
||||
informers: informers,
|
||||
resources: resourceGetter,
|
||||
kubeClient: kubeClient,
|
||||
informers: informers,
|
||||
ksClient: ksClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (am *amOperator) GetPlatformRole(username string) (Role, error) {
|
||||
panic("implement me")
|
||||
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) GetClusterRole(cluster, username string) (Role, error) {
|
||||
panic("implement me")
|
||||
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 (am *amOperator) GetWorkspaceRole(workspace, username string) (Role, error) {
|
||||
panic("implement me")
|
||||
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) GetNamespaceRole(cluster, namespace, username string) (Role, error) {
|
||||
panic("implement me")
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1,141 +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 am
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
)
|
||||
|
||||
type FakeRole struct {
|
||||
Name string
|
||||
Rego string
|
||||
}
|
||||
type FakeOperator struct {
|
||||
cache cache.Interface
|
||||
}
|
||||
|
||||
func (f FakeOperator) queryFakeRole(cacheKey string) (Role, error) {
|
||||
data, err := f.cache.Get(cacheKey)
|
||||
if err != nil {
|
||||
if err == cache.ErrNoSuchKey {
|
||||
return &FakeRole{
|
||||
Name: "DenyAll",
|
||||
Rego: "package authz\ndefault allow = false",
|
||||
}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
var role FakeRole
|
||||
err = json.Unmarshal([]byte(data), &role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func (f FakeOperator) saveFakeRole(cacheKey string, role FakeRole) error {
|
||||
data, err := json.Marshal(role)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.cache.Set(cacheKey, string(data), 0)
|
||||
}
|
||||
|
||||
func (f FakeOperator) GetPlatformRole(username string) (Role, error) {
|
||||
return f.queryFakeRole(platformRoleCacheKey(username))
|
||||
}
|
||||
|
||||
func (f FakeOperator) GetClusterRole(cluster, username string) (Role, error) {
|
||||
return f.queryFakeRole(clusterRoleCacheKey(cluster, username))
|
||||
}
|
||||
|
||||
func (f FakeOperator) GetWorkspaceRole(workspace, username string) (Role, error) {
|
||||
return f.queryFakeRole(workspaceRoleCacheKey(workspace, username))
|
||||
}
|
||||
|
||||
func (f FakeOperator) GetNamespaceRole(cluster, namespace, username string) (Role, error) {
|
||||
return f.queryFakeRole(namespaceRoleCacheKey(cluster, namespace, username))
|
||||
}
|
||||
|
||||
func (f FakeOperator) Prepare(platformRoles map[string]FakeRole, clusterRoles map[string]map[string]FakeRole, workspaceRoles map[string]map[string]FakeRole, namespaceRoles map[string]map[string]map[string]FakeRole) {
|
||||
|
||||
for username, role := range platformRoles {
|
||||
f.saveFakeRole(platformRoleCacheKey(username), role)
|
||||
}
|
||||
for cluster, roles := range clusterRoles {
|
||||
for username, role := range roles {
|
||||
f.saveFakeRole(clusterRoleCacheKey(cluster, username), role)
|
||||
}
|
||||
}
|
||||
|
||||
for workspace, roles := range workspaceRoles {
|
||||
for username, role := range roles {
|
||||
f.saveFakeRole(workspaceRoleCacheKey(workspace, username), role)
|
||||
}
|
||||
}
|
||||
|
||||
for cluster, nsRoles := range namespaceRoles {
|
||||
for namespace, roles := range nsRoles {
|
||||
for username, role := range roles {
|
||||
f.saveFakeRole(namespaceRoleCacheKey(cluster, namespace, username), role)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func namespaceRoleCacheKey(cluster, namespace, username string) string {
|
||||
return fmt.Sprintf("cluster.%s.namespaces.%s.roles.%s", cluster, namespace, username)
|
||||
}
|
||||
|
||||
func clusterRoleCacheKey(cluster, username string) string {
|
||||
return fmt.Sprintf("cluster.%s.roles.%s", cluster, username)
|
||||
}
|
||||
func workspaceRoleCacheKey(workspace, username string) string {
|
||||
return fmt.Sprintf("workspace.%s.roles.%s", workspace, username)
|
||||
}
|
||||
|
||||
func platformRoleCacheKey(username string) string {
|
||||
return fmt.Sprintf("platform.roles.%s", username)
|
||||
}
|
||||
|
||||
func (f FakeRole) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
func (f FakeRole) GetRego() string {
|
||||
return f.Rego
|
||||
}
|
||||
|
||||
func NewFakeAMOperator() *FakeOperator {
|
||||
operator := &FakeOperator{cache: cache.NewSimpleCache()}
|
||||
operator.saveFakeRole(platformRoleCacheKey("admin"), FakeRole{
|
||||
Name: "admin",
|
||||
Rego: "package authz\ndefault allow = true",
|
||||
})
|
||||
operator.saveFakeRole(platformRoleCacheKey(user.Anonymous), FakeRole{
|
||||
Name: "admin",
|
||||
Rego: `package authz
|
||||
default allow = false
|
||||
`,
|
||||
})
|
||||
return operator
|
||||
}
|
||||
Reference in New Issue
Block a user