forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
storage.go
120 lines (99 loc) · 4.03 KB
/
storage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package subjectrulesreview
import (
"fmt"
"sort"
kapierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
kutilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apiserver/pkg/authentication/user"
apirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/kubernetes/pkg/apis/rbac"
rbaclisters "k8s.io/kubernetes/pkg/client/listers/rbac/internalversion"
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
"github.com/openshift/origin/pkg/authorization/authorizer/scope"
)
type REST struct {
ruleResolver rbacregistryvalidation.AuthorizationRuleResolver
clusterRoleGetter rbaclisters.ClusterRoleLister
}
var _ rest.Creater = &REST{}
func NewREST(ruleResolver rbacregistryvalidation.AuthorizationRuleResolver, clusterRoleGetter rbaclisters.ClusterRoleLister) *REST {
return &REST{ruleResolver: ruleResolver, clusterRoleGetter: clusterRoleGetter}
}
func (r *REST) New() runtime.Object {
return &authorizationapi.SubjectRulesReview{}
}
// Create registers a given new ResourceAccessReview instance to r.registry.
func (r *REST) Create(ctx apirequest.Context, obj runtime.Object, _ bool) (runtime.Object, error) {
rulesReview, ok := obj.(*authorizationapi.SubjectRulesReview)
if !ok {
return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a SubjectRulesReview: %#v", obj))
}
namespace := apirequest.NamespaceValue(ctx)
if len(namespace) == 0 {
return nil, kapierrors.NewBadRequest(fmt.Sprintf("namespace is required on this type: %v", namespace))
}
userToCheck := &user.DefaultInfo{
Name: rulesReview.Spec.User,
Groups: rulesReview.Spec.Groups,
Extra: map[string][]string{},
}
if len(rulesReview.Spec.Scopes) > 0 {
userToCheck.Extra[authorizationapi.ScopesKey] = rulesReview.Spec.Scopes
}
rules, errors := GetEffectivePolicyRules(apirequest.WithUser(ctx, userToCheck), r.ruleResolver, r.clusterRoleGetter)
ret := &authorizationapi.SubjectRulesReview{
Status: authorizationapi.SubjectRulesReviewStatus{
Rules: authorizationapi.Convert_rbac_PolicyRules_To_authorization_PolicyRules(rules), //TODO can we fix this ?
},
}
if len(errors) != 0 {
ret.Status.EvaluationError = kutilerrors.NewAggregate(errors).Error()
}
return ret, nil
}
func GetEffectivePolicyRules(ctx apirequest.Context, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver, clusterRoleGetter rbaclisters.ClusterRoleLister) ([]rbac.PolicyRule, []error) {
namespace := apirequest.NamespaceValue(ctx)
if len(namespace) == 0 {
return nil, []error{kapierrors.NewBadRequest(fmt.Sprintf("namespace is required on this type: %v", namespace))}
}
user, exists := apirequest.UserFrom(ctx)
if !exists {
return nil, []error{kapierrors.NewBadRequest(fmt.Sprintf("user missing from context"))}
}
var errors []error
var rules []rbac.PolicyRule
namespaceRules, err := ruleResolver.RulesFor(user, namespace)
if err != nil {
errors = append(errors, err)
}
for _, rule := range namespaceRules {
rules = append(rules, rbacregistryvalidation.BreakdownRule(rule)...)
}
if scopes := user.GetExtra()[authorizationapi.ScopesKey]; len(scopes) > 0 {
rules, err = filterRulesByScopes(rules, scopes, namespace, clusterRoleGetter)
if err != nil {
return nil, []error{kapierrors.NewInternalError(err)}
}
}
if compactedRules, err := rbacregistryvalidation.CompactRules(rules); err == nil {
rules = compactedRules
}
sort.Sort(rbac.SortableRuleSlice(rules))
return rules, errors
}
func filterRulesByScopes(rules []rbac.PolicyRule, scopes []string, namespace string, clusterRoleGetter rbaclisters.ClusterRoleLister) ([]rbac.PolicyRule, error) {
scopeRules, err := scope.ScopesToRules(scopes, namespace, clusterRoleGetter)
if err != nil {
return nil, err
}
filteredRules := []rbac.PolicyRule{}
for _, rule := range rules {
if allowed, _ := rbacregistryvalidation.Covers(scopeRules, []rbac.PolicyRule{rule}); allowed {
filteredRules = append(filteredRules, rule)
}
}
return filteredRules, nil
}