@@ -51,6 +51,9 @@ type Attributes interface {
|
||||
// The namespace of the object, if a request is for a REST object.
|
||||
GetNamespace() string
|
||||
|
||||
// The devops project of the object, if a request is for a REST object.
|
||||
GetDevOps() string
|
||||
|
||||
// The kind of object, if a request is for a REST object.
|
||||
GetResource() string
|
||||
|
||||
@@ -109,6 +112,7 @@ type AttributesRecord struct {
|
||||
Cluster string
|
||||
Workspace string
|
||||
Namespace string
|
||||
DevOps string
|
||||
APIGroup string
|
||||
APIVersion string
|
||||
Resource string
|
||||
@@ -144,6 +148,10 @@ func (a AttributesRecord) GetNamespace() string {
|
||||
return a.Namespace
|
||||
}
|
||||
|
||||
func (a AttributesRecord) GetDevOps() string {
|
||||
return a.DevOps
|
||||
}
|
||||
|
||||
func (a AttributesRecord) GetResource() string {
|
||||
return a.Resource
|
||||
}
|
||||
|
||||
@@ -234,11 +234,21 @@ func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes,
|
||||
}
|
||||
}
|
||||
|
||||
if requestAttributes.GetResourceScope() == request.WorkspaceScope || requestAttributes.GetResourceScope() == request.NamespaceScope {
|
||||
if requestAttributes.GetResourceScope() == request.WorkspaceScope ||
|
||||
requestAttributes.GetResourceScope() == request.NamespaceScope ||
|
||||
requestAttributes.GetResourceScope() == request.DevOpsScope {
|
||||
|
||||
var workspace string
|
||||
var err error
|
||||
// all of resource under namespace and devops belong to workspace
|
||||
if requestAttributes.GetResourceScope() == request.NamespaceScope {
|
||||
if workspace, err = r.am.GetControlledWorkspace(requestAttributes.GetNamespace()); err != nil {
|
||||
if workspace, err = r.am.GetNamespaceControlledWorkspace(requestAttributes.GetNamespace()); err != nil {
|
||||
if !visitor(nil, "", nil, err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if requestAttributes.GetResourceScope() == request.DevOpsScope {
|
||||
if workspace, err = r.am.GetDevOpsControlledWorkspace(requestAttributes.GetDevOps()); err != nil {
|
||||
if !visitor(nil, "", nil, err) {
|
||||
return
|
||||
}
|
||||
@@ -279,19 +289,33 @@ func (r *RBACAuthorizer) visitRulesFor(requestAttributes authorizer.Attributes,
|
||||
}
|
||||
}
|
||||
|
||||
if requestAttributes.GetResourceScope() == request.NamespaceScope {
|
||||
if roleBindings, err := r.am.ListRoleBindings("", requestAttributes.GetNamespace()); err != nil {
|
||||
if requestAttributes.GetResourceScope() == request.NamespaceScope ||
|
||||
requestAttributes.GetResourceScope() == request.DevOpsScope {
|
||||
|
||||
namespace := requestAttributes.GetNamespace()
|
||||
// list devops role binding
|
||||
if requestAttributes.GetResourceScope() == request.DevOpsScope {
|
||||
if relatedNamespace, err := r.am.GetDevOpsRelatedNamespace(requestAttributes.GetDevOps()); err != nil {
|
||||
if !visitor(nil, "", nil, err) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
namespace = relatedNamespace
|
||||
}
|
||||
}
|
||||
|
||||
if roleBindings, err := r.am.ListRoleBindings("", namespace); err != nil {
|
||||
if !visitor(nil, "", nil, err) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
sourceDescriber := &roleBindingDescriber{}
|
||||
for _, roleBinding := range roleBindings {
|
||||
subjectIndex, applies := appliesTo(requestAttributes.GetUser(), roleBinding.Subjects, requestAttributes.GetNamespace())
|
||||
subjectIndex, applies := appliesTo(requestAttributes.GetUser(), roleBinding.Subjects, namespace)
|
||||
if !applies {
|
||||
continue
|
||||
}
|
||||
regoPolicy, rules, err := r.am.GetRoleReferenceRules(roleBinding.RoleRef, requestAttributes.GetNamespace())
|
||||
regoPolicy, rules, err := r.am.GetRoleReferenceRules(roleBinding.RoleRef, namespace)
|
||||
if err != nil {
|
||||
visitor(nil, "", nil, err)
|
||||
continue
|
||||
|
||||
@@ -82,12 +82,12 @@ func getAuthorizerAttributes(ctx context.Context) (authorizer.Attributes, error)
|
||||
attribs.Cluster = requestInfo.Cluster
|
||||
attribs.Workspace = requestInfo.Workspace
|
||||
attribs.KubernetesRequest = requestInfo.IsKubernetesRequest
|
||||
|
||||
attribs.APIGroup = requestInfo.APIGroup
|
||||
attribs.APIVersion = requestInfo.APIVersion
|
||||
attribs.Resource = requestInfo.Resource
|
||||
attribs.Subresource = requestInfo.Subresource
|
||||
attribs.Namespace = requestInfo.Namespace
|
||||
attribs.DevOps = requestInfo.DevOps
|
||||
attribs.Name = requestInfo.Name
|
||||
|
||||
return &attribs, nil
|
||||
|
||||
@@ -69,6 +69,9 @@ type RequestInfo struct {
|
||||
// Cluster of requested resource, this is empty in single-cluster environment
|
||||
Cluster string
|
||||
|
||||
// DevOps project of requested resource
|
||||
DevOps string
|
||||
|
||||
// Scope of requested resource.
|
||||
ResourceScope string
|
||||
}
|
||||
@@ -195,15 +198,6 @@ func (r *RequestInfoFactory) NewRequestInfo(req *http.Request) (*RequestInfo, er
|
||||
}
|
||||
}
|
||||
|
||||
selector := req.URL.Query().Get("labelSelector")
|
||||
// URL forms: /api/v1/watch/namespaces?labelSelector=kubesphere.io/workspace=system-workspace
|
||||
if strings.HasPrefix(selector, workspaceSelectorPrefix) {
|
||||
workspace := strings.TrimPrefix(selector, workspaceSelectorPrefix)
|
||||
// URL forms: /api/v1/watch/namespaces?labelSelector=kubesphere.io/workspace==system-workspace
|
||||
workspace = strings.TrimPrefix(workspace, "=")
|
||||
requestInfo.Workspace = workspace
|
||||
}
|
||||
|
||||
// URL forms: /namespaces/{namespace}/{kind}/*, where parts are adjusted to be relative to kind
|
||||
if currentParts[0] == "namespaces" {
|
||||
if len(currentParts) > 1 {
|
||||
@@ -215,8 +209,19 @@ func (r *RequestInfoFactory) NewRequestInfo(req *http.Request) (*RequestInfo, er
|
||||
currentParts = currentParts[2:]
|
||||
}
|
||||
}
|
||||
} else if currentParts[0] == "devops" {
|
||||
if len(currentParts) > 1 {
|
||||
requestInfo.DevOps = currentParts[1]
|
||||
|
||||
// if there is another step after the devops name
|
||||
// move currentParts to include it as a resource in its own right
|
||||
if len(currentParts) > 2 {
|
||||
currentParts = currentParts[2:]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
requestInfo.Namespace = metav1.NamespaceNone
|
||||
requestInfo.DevOps = metav1.NamespaceNone
|
||||
}
|
||||
|
||||
// parsing successful, so we now know the proper value for .Parts
|
||||
@@ -260,6 +265,15 @@ func (r *RequestInfoFactory) NewRequestInfo(req *http.Request) (*RequestInfo, er
|
||||
requestInfo.Verb = "list"
|
||||
}
|
||||
|
||||
// URL forms: /api/v1/watch/namespaces?labelSelector=kubesphere.io/workspace=system-workspace
|
||||
if requestInfo.Verb == "watch" {
|
||||
selector := req.URL.Query().Get("labelSelector")
|
||||
if strings.HasPrefix(selector, workspaceSelectorPrefix) {
|
||||
workspace := strings.TrimPrefix(selector, workspaceSelectorPrefix)
|
||||
requestInfo.Workspace = workspace
|
||||
}
|
||||
}
|
||||
|
||||
if opts.FieldSelector != nil {
|
||||
if name, ok := opts.FieldSelector.RequiresExactMatch("metadata.name"); ok {
|
||||
if len(path.IsValidPathSegmentName(name)) == 0 {
|
||||
@@ -306,6 +320,7 @@ const (
|
||||
ClusterScope = "Cluster"
|
||||
WorkspaceScope = "Workspace"
|
||||
NamespaceScope = "Namespace"
|
||||
DevOpsScope = "DevOps"
|
||||
workspaceSelectorPrefix = constants.WorkspaceLabelKey + "="
|
||||
)
|
||||
|
||||
@@ -318,6 +333,10 @@ func (r *RequestInfoFactory) resolveResourceScope(request RequestInfo) string {
|
||||
return NamespaceScope
|
||||
}
|
||||
|
||||
if request.DevOps != "" {
|
||||
return DevOpsScope
|
||||
}
|
||||
|
||||
if request.Workspace != "" {
|
||||
return WorkspaceScope
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user